1 2 3<!DOCTYPE html> 4<html lang="tr"> 5<head> 6 <meta charset="UTF-8"> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 8 <title>Kayıt Ol - ProParcel</title> 9 10<link rel="icon" type="image/x-icon" href="/static/img/favicon.ico" /> 11 12 <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"> 13 <link rel="preload" as="image" href="/media/landingpage/sluet3.png" fetchpriority="high"> 14 15<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/select2.min.css" rel="stylesheet"> 16<link rel="stylesheet" href="/static/frontend/assets/authPortal-CikBl9lS.css?v=1788697666221026500"> 17<link rel="stylesheet" href="/static/frontend/assets/landing-MYcNrV8P.css?v=1788697666221026500"> 18<style> 19 /* TTBS DoÄrulama Stilleri */ 20 .input-with-status { 21 position: relative; 22 display: flex; 23 align-items: center; 24 } 25 26 .input-with-status .form-input { 27 flex: 1; 28 padding-right: 40px; 29 } 30 31 .validation-icon { 32 position: absolute; 33 right: 12px; 34 top: 50%; 35 transform: translateY(-50%); 36 display: flex; 37 align-items: center; 38 justify-content: center; 39 font-size: 1rem; 40 } 41 42 .ttbs-status { 43 font-size: 0.8rem; 44 margin-top: 4px; 45 padding: 4px 8px; 46 border-radius: 4px; 47 } 48 49 .ttbs-info-box { 50 margin-top: 12px; 51 padding: 12px 16px; 52 background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%); 53 border: 1px solid #10b981; 54 border-radius: 8px; 55 animation: slideDown 0.3s ease-out; 56 } 57 58 @keyframes slideDown { 59 from { 60 opacity: 0; 61 transform: translateY(-10px); 62 } 63 to { 64 opacity: 1; 65 transform: translateY(0); 66 } 67 } 68 69 .ttbs-info-header { 70 display: flex; 71 align-items: center; 72 gap: 8px; 73 color: #059669; 74 font-weight: 600; 75 font-size: 0.9rem; 76 margin-bottom: 10px; 77 padding-bottom: 8px; 78 border-bottom: 1px solid rgba(16, 185, 129, 0.2); 79 } 80 81 .ttbs-info-header i { 82 font-size: 1rem; 83 } 84 85 .ttbs-info-content { 86 display: flex; 87 flex-direction: column; 88 gap: 6px; 89 } 90 91 .ttbs-info-row { 92 display: flex; 93 gap: 8px; 94 font-size: 0.8rem; 95 line-height: 1.4; 96 } 97 98 .ttbs-label { 99 color: #6b7280; 100 min-width: 100px; 101 flex-shrink: 0; 102 } 103 104 .ttbs-value { 105 color: #1f2937; 106 font-weight: 500; 107 } 108 109 /* Kayıt saÄ kolon â kurumsal üye bilgilendirmesi */ 110 .auth-register-corporate-note { 111 margin: 0 0 28px; 112 padding: 14px 16px; 113 font-size: 0.98rem; 114 font-weight: 600; 115 line-height: 1.55; 116 color: var(--text, #0f172a); 117 background: linear-gradient(180deg, #fffbeb 0%, #fef3c7 100%); 118 border: 1px solid #fcd34d; 119 border-left: 4px solid #d97706; 120 border-radius: 8px; 121 box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06); 122 } 123 124 /* Kurumsal Firma Tipi Seçim Butonları */ 125 .corporate-type-buttons { 126 display: flex; 127 gap: 12px; 128 margin-bottom: 12px; 129 } 130 .corporate-type-btn { 131 flex: 1; 132 padding: 12px 16px; 133 border: 1px solid var(--border, #e5e7eb); 134 border-radius: 8px; 135 font-size: 0.9rem; 136 font-weight: 500; 137 cursor: pointer; 138 transition: all 0.2s; 139 } 140 .corporate-type-btn:not(.active) { 141 background: rgba(0, 0, 0, 0.03); 142 color: var(--text-muted, #9ca3af); 143 border-color: rgba(0, 0, 0, 0.08); 144 opacity: 0.85; 145 } 146 .corporate-type-btn:not(.active):hover { 147 opacity: 1; 148 border-color: var(--border, #e5e7eb); 149 color: var(--text-secondary, #6b7280); 150 } 151 .corporate-type-btn.active { 152 border-color: var(--primary, #1a5fb4); 153 background: rgba(26, 95, 180, 0.1); 154 color: var(--primary, #1a5fb4); 155 opacity: 1; 156 } 157 158 /* Dark mode desteÄi */ 159 @media (prefers-color-scheme: dark) { 160 .ttbs-info-box { 161 background: linear-gradient(135deg, #064e3b 0%, #065f46 100%); 162 border-color: #10b981; 163 } 164 165 .ttbs-info-header { 166 color: #34d399; 167 border-bottom-color: rgba(52, 211, 153, 0.2); 168 } 169 170 .ttbs-label { 171 color: #9ca3af; 172 } 173 174 .ttbs-value { 175 color: #f3f4f6; 176 } 177 } 178 179 /* Mezuniyet Bölümü Stilleri */ 180 .graduation-section { 181 margin-top: 24px; 182 padding: 20px; 183 background: rgba(59, 130, 246, 0.05); 184 border: 1px solid rgba(59, 130, 246, 0.2); 185 border-radius: 12px; 186 } 187 188 .graduation-section-title { 189 display: flex; 190 align-items: center; 191 gap: 8px; 192 font-size: 1rem; 193 font-weight: 600; 194 color: var(--text-primary); 195 margin-bottom: 12px; 196 } 197 198 .graduation-required-badge { 199 font-size: 0.75rem; 200 color: var(--danger, #dc3545); 201 margin-left: 8px; 202 font-weight: 600; 203 } 204 .graduation-section-title i { 205 color: #3b82f6; 206 } 207 208 .graduation-info-note { 209 background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); 210 border: 1px solid #f59e0b; 211 border-radius: 8px; 212 padding: 12px 16px; 213 margin-bottom: 16px; 214 font-size: 0.85rem; 215 color: #92400e; 216 display: flex; 217 align-items: flex-start; 218 gap: 10px; 219 } 220 221 .graduation-info-note i { 222 color: #f59e0b; 223 margin-top: 2px; 224 flex-shrink: 0; 225 } 226 227 @media (prefers-color-scheme: dark) { 228 .graduation-info-note { 229 background: linear-gradient(135deg, #78350f 0%, #92400e 100%); 230 border-color: #f59e0b; 231 color: #fef3c7; 232 } 233 } 234 235 .education-level-options { 236 display: flex; 237 gap: 16px; 238 margin-bottom: 16px; 239 flex-wrap: wrap; 240 } 241 242 .education-level-option { 243 display: flex; 244 align-items: center; 245 gap: 8px; 246 cursor: pointer; 247 padding: 10px 16px; 248 border: 2px solid var(--border, #e5e7eb); 249 border-radius: 8px; 250 transition: all 0.2s; 251 flex: 1; 252 min-width: 120px; 253 background: rgba(0,0,0,0.03); 254 color: var(--text-muted, #9ca3af); 255 opacity: 0.85; 256 } 257 258 .education-level-option:not(.selected):hover { 259 opacity: 1; 260 border-color: var(--border, #e5e7eb); 261 color: var(--text-secondary, #6b7280); 262 } 263 264 .education-level-option input[type="radio"] { 265 width: 18px; 266 height: 18px; 267 accent-color: #3b82f6; 268 } 269 270 .education-level-option.selected { 271 border-color: #3b82f6; 272 background: rgba(59, 130, 246, 0.15); 273 color: #3b82f6; 274 opacity: 1; 275 } 276 277 .higher-education-fields { 278 display: none; 279 margin-top: 16px; 280 padding-top: 16px; 281 border-top: 1px solid rgba(255,255,255,0.1); 282 } 283 284 .higher-education-fields.visible { 285 display: block; 286 animation: slideDown 0.3s ease-out; 287 } 288 289 .diploma-upload-section { 290 margin-top: 16px; 291 padding: 16px; 292 background: rgba(255,255,255,0.03); 293 border: 1px dashed rgba(255,255,255,0.2); 294 border-radius: 8px; 295 text-align: center; 296 } 297 298 .diploma-upload-section label { 299 cursor: pointer; 300 display: inline-flex; 301 align-items: center; 302 gap: 8px; 303 padding: 10px 20px; 304 background: var(--primary); 305 color: white; 306 border-radius: 6px; 307 font-size: 0.9rem; 308 transition: background 0.2s; 309 } 310 311 .diploma-upload-section label:hover { 312 background: var(--primary-hover, #1e3a8a); 313 color: white; 314 } 315 316 .diploma-preview { 317 margin-top: 12px; 318 font-size: 0.85rem; 319 color: var(--text-secondary); 320 } 321 322 .diploma-preview .file-name { 323 display: flex; 324 align-items: center; 325 justify-content: center; 326 gap: 8px; 327 color: #10b981; 328 } 329 330 .skip-diploma-option { 331 margin-top: 12px; 332 display: flex; 333 align-items: center; 334 justify-content: center; 335 gap: 8px; 336 font-size: 0.85rem; 337 color: var(--text-muted, #9ca3af); 338 opacity: 0.7; 339 } 340 341 .skip-diploma-option input[type="checkbox"] { 342 width: 16px; 343 height: 16px; 344 accent-color: #9ca3af; 345 } 346 347 .auth-left-content { 348 text-align: center; 349 display: flex; 350 flex-direction: column; 351 justify-content: flex-start; 352 align-items: stretch; 353 width: 100%; 354 min-height: 0; 355 } 356 357 .auth-logo-large { 358 text-align: center; 359 } 360 361 .auth-description { 362 text-align: center; 363 font-size: 1rem; 364 } 365 366 .auth-features { 367 width: fit-content; 368 max-width: 100%; 369 margin-left: auto; 370 margin-right: auto; 371 display: flex; 372 flex-direction: column; 373 align-items: stretch; 374 gap: 0; 375 } 376 377 .auth-features li { 378 align-items: flex-start; 379 margin-bottom: 6px; 380 gap: 8px; 381 } 382 383 .auth-features li span { 384 display: block; 385 text-align: left; 386 font-size: 0.95rem; 387 } 388 389 /* Ãyelik tipi seçim kartları */ 390 .register-type-step-lead { 391 margin: 0 0 20px; 392 font-size: 1rem; 393 font-weight: 600; 394 color: var(--text-secondary, #64748b); 395 text-align: center; 396 } 397 398 .register-type-cards { 399 display: flex; 400 flex-direction: column; 401 gap: 14px; 402 margin-bottom: 8px; 403 } 404 405 .register-type-card { 406 position: relative; 407 display: flex; 408 flex-direction: column; 409 align-items: flex-start; 410 gap: 8px; 411 width: 100%; 412 padding: 16px 18px; 413 padding-top: 18px; 414 border: 2px solid transparent; 415 border-radius: 14px; 416 text-align: left; 417 cursor: pointer; 418 transition: transform 0.15s ease, box-shadow 0.15s ease; 419 overflow: visible; 420 } 421 422 .register-type-card__badge { 423 position: absolute; 424 top: 12px; 425 right: 12px; 426 z-index: 2; 427 padding: 5px 10px; 428 border-radius: 999px; 429 background: linear-gradient(135deg, #34d399 0%, #059669 100%); 430 color: #fff; 431 font-size: 0.72rem; 432 font-weight: 800; 433 letter-spacing: 0.02em; 434 line-height: 1.2; 435 border: 1px solid rgba(255, 255, 255, 0.45); 436 box-shadow: 0 2px 8px rgba(6, 78, 59, 0.35); 437 pointer-events: none; 438 } 439 440 .register-type-card:hover { 441 transform: translateY(-1px); 442 box-shadow: 0 6px 18px rgba(15, 23, 42, 0.12); 443 } 444 445 .register-type-card__icon { 446 font-size: 1.25rem; 447 line-height: 1; 448 } 449 450 .register-type-card__title { 451 font-size: 1.05rem; 452 font-weight: 700; 453 } 454 455 .register-type-card__desc { 456 font-size: 0.92rem; 457 line-height: 1.55; 458 } 459 460 .register-type-card--corporate { 461 background: #062B5F; 462 color: #fff; 463 } 464 465 .register-type-card--corporate .register-type-card__desc { 466 color: rgba(255, 255, 255, 0.86); 467 } 468 469 .register-type-card--consultant { 470 background: #00A6D6; 471 color: #fff; 472 } 473 474 .register-type-card--consultant .register-type-card__desc { 475 color: rgba(255, 255, 255, 0.9); 476 } 477 478 .register-type-card--individual { 479 background: #fff; 480 color: #062B5F; 481 border-color: #DDE3EC; 482 } 483 484 .register-type-card--individual .register-type-card__desc { 485 color: #64748B; 486 } 487 488 .register-selected-type-bar { 489 display: flex; 490 align-items: center; 491 justify-content: space-between; 492 gap: 12px; 493 margin-bottom: 20px; 494 padding: 12px 14px; 495 background: #f8fafc; 496 border: 1px solid #e2e8f0; 497 border-radius: 10px; 498 } 499 500 .register-selected-type-bar__text { 501 font-size: 0.92rem; 502 color: #64748b; 503 } 504 505 .register-change-type-btn { 506 border: none; 507 background: transparent; 508 color: #1a5fb4; 509 font-size: 0.92rem; 510 font-weight: 600; 511 cursor: pointer; 512 padding: 0; 513 } 514 515 .register-change-type-btn:hover { 516 text-decoration: underline; 517 } 518 519</style> 520<link rel="stylesheet" href="/static/css/auth-portal-register-legacy.css"> 521 522</head> 523<body class="pp-auth-portal-page "> 524 <div 525 id="auth-portal-page" 526 class="pp-auth-portal" 527 data-mode="register" 528 data-hero-bg="/media/landingpage/sluet3.png" 529 data-favicon="/static/img/favicon.ico" 530 > 531 <div class="pp-auth-portal__bg" aria-hidden="true"></div> 532 <div class="pp-auth-portal__outer"> 533 <div class="pp-auth-portal__shell"> 534 <div id="auth-portal-branding" aria-label="ProParcel tanıtım"></div> 535 <div class="pp-auth-portal__forms"> 536 <div class="pp-auth-portal__forms-logo-spacer" aria-hidden="true"></div> 537 <div class="pp-auth-portal__forms-body"> 538 <div class="pp-auth-portal__forms-scroll"> 539 540<div class="pp-auth-panel pp-auth-panel--register pp-auth-panel--enter"> 541 <header class="pp-auth-panel__head"> 542 <h1 class="pp-auth-panel__title">Hesabınızı OluÅturun</h1> 543 <p class="pp-auth-panel__lead">ProParcel'e katılın, arazi analizlerinde fark yaratın.</p> 544 </header> 545 546 547<div class="pp-auth-legacy-register"> 548 549 550 551 552 <!-- Kayıt Kontrolü Uyarısı --> 553 554 555 <!-- Global Error Display -->
556 <div id="global-error" class="alert alert-error" style="display: none; margin-bottom: 24px;"></div> 557 558 559 <div id="register-type-step" class="register-type-step"> 560 <p class="register-type-step-lead">Ãyelik tipinizi seçin</p> 561 <div class="register-type-cards"> 562 <button type="button" class="register-type-card register-type-card--corporate" data-member-type="corporate"> 563 <span class="register-type-card__badge">Fiyat Avantajı</span> 564 <span class="register-type-card__icon" aria-hidden="true"><i class="fas fa-building"></i></span> 565 <span class="register-type-card__title">Kurumsal</span> 566 <span class="register-type-card__desc">Emlak, SPK ve LİHKAB ofisleri bu alandan üyelik oluÅturabilir. <strong>Ãnemli:</strong> Firmada çalıÅmayan, yetki belgesine sahip baÄımsız emlak danıÅmanları da bu alanı kullanmalıdır.</span> 567 </button> 568 <button type="button" class="register-type-card register-type-card--consultant" data-member-type="consultant"> 569 <span class="register-type-card__badge">Fiyat Avantajı</span> 570 <span class="register-type-card__icon" aria-hidden="true"><i class="fas fa-user-tie"></i></span> 571 <span class="register-type-card__title">DanıÅman</span> 572 <span class="register-type-card__desc">Emlak, SPK ve LİHKAB ofislerinde çalıÅan emlak danıÅmanları bu alandan kayıt olmalıdır.</span> 573 </button> 574 <button type="button" class="register-type-card register-type-card--individual" data-member-type="individual"> 575 <span class="register-type-card__icon" aria-hidden="true"><i class="fas fa-user"></i></span> 576 <span class="register-type-card__title">Bireysel</span> 577 <span class="register-type-card__desc">Bireysel kullanıcılar için üyelik kayıt alanıdır.</span> 578 </button> 579 </div> 580 </div> 581 582 583 <div id="register-form-area" style="display: none;"> 584 585 <div id="register-selected-type-bar" class="register-selected-type-bar" style="display: none;"> 586 <span class="register-selected-type-bar__text">Seçilen üyelik tipi: <strong id="register-selected-type-label"></strong></span> 587 <button type="button" id="register-change-type-btn" class="register-change-type-btn">DeÄiÅtir</button> 588 </div> 589 590 591 592 593 <!-- Member Type Hidden Input (for tab switching) --> 594 <input type="hidden" id="member_type" value="individual"> 595 596 <!-- Bireysel Form --> 597 <form method="post" action="/accounts/register/" enctype="multipart/form-data" id="form-individual" style="display: block;"> 598 <input type="hidden" name="csrfmiddlewaretoken" value="2xg8q9AbyLEo0yB67DYqwtzSNqmTnnvKkOIpAfKv6P0pdiB03cg85F6ZPOqGSqps"> 599 <input type="hidden" name="member_type" value="individual"> 600 601 <!-- Adım 1: Genel Bilgiler - Bireysel --> 602 <div id="step-validate-info-individual" class="register-step active" style="display: block;"> 603 <!-- Ad, Soyad - Yan yana --> 604 <div class="form-row"> 605 <div class="form-group form-group-half"> 606 <input 607 type="text" 608 id="first_name_individual" 609 name="first_name" 610 class="form-input " 611 placeholder="Adınız *" 612 value="" 613 required 614 autocomplete="given-name" 615 > 616 <div class="form-error" id="error-first_name_individual" style="display: none;"></div> 617 618 </div> 619 620 <div class="form-group form-group-half"> 621 <input 622 type="text" 623 id="last_name_individual" 624 name="last_name" 625 class="form-input " 626 placeholder="Soyadınız *" 627 value="" 628 required 629 autocomplete="family-name" 630 > 631 <div class="form-error" id="error-last_name_individual" style="display: none;"></div> 632 633 </div> 634 </div> 635 636 <!-- Email --> 637 <div class="form-group"> 638 <input 639 type="email" 640 id="email_individual" 641 name="email" 642 class="form-input " 643 placeholder="E-posta Adresi *" 644 value="" 645 required 646 autocomplete="email" 647 > 648 <div class="form-error" id="error-email_individual" style="display: none;"></div> 649 650 </div> 651 652 <!-- Phone --> 653 <div class="form-group"> 654 <div class="phone-input-group">
655 <span class="phone-prefix">+90</span> 656 <input 657 type="tel" 658 id="phone_number_individual" 659 name="phone_number" 660 class="form-input " 661 placeholder="Telefon Numarası" 662 maxlength="10" 663 pattern="[0-9]{10}" 664 value="" 665 autocomplete="tel" 666 > 667 </div> 668 <div class="form-hint" style="font-size: 0.75rem; margin-top: 4px; color: var(--text-secondary, #9ca3af);">Zorunlu deÄildir</div> 669 <div class="form-error" id="error-phone_number_individual" style="display: none;"></div> 670 671 </div> 672 673 <!-- Password --> 674 <div class="form-row"> 675 <div class="form-group form-group-half"> 676 <input 677 type="password" 678 id="password_individual" 679 name="password" 680 class="form-input " 681 placeholder="Åifre (En az 8 karakter, bir büyük harf) *" 682 minlength="8" required 683 autocomplete="new-password" 684 > 685 <ul class="password-rules" id="password-rules-individual" aria-live="polite"> 686 <li class="password-rule is-fail" data-rule="minLength"><span class="password-rule__mark" aria-hidden="true">â</span> En az 8 karakter</li> 687 <li class="password-rule is-fail" data-rule="uppercase"><span class="password-rule__mark" aria-hidden="true">â</span> En az bir büyük harf</li> 688 </ul> 689 <div id="password-error-individual" class="form-error" style="display: none;"></div> 690 691 </div> 692 693 <div class="form-group form-group-half"> 694 <input 695 type="password" 696 id="password_confirm_individual" 697 name="password_confirm" 698 class="form-input " 699 placeholder="Åifre Tekrar *" 700 minlength="8" required 701 autocomplete="new-password" 702 > 703 <div id="password-match-error-individual" class="form-error" style="display: none;"></div> 704 705 </div> 706 </div> 707 708 <div class="referral-phone-card"> 709 <div class="referral-phone-card__header"> 710 <span class="referral-phone-card__badge"><i class="fas fa-gift" aria-hidden="true"></i> Referans</span> 711 <span class="referral-phone-card__optional">Zorunlu deÄildir</span> 712 </div> 713 <p class="referral-phone-card__lead"> 714 Size referans olan üyemizin numarasını girin, 715 <strong><span class="referral-phone-bonus-amount">5</span> kredi hediye</strong> kazanın. 716 </p> 717 <div class="phone-input-group"> 718 <span class="phone-prefix">+90</span> 719 <input 720 type="tel" 721 id="referral_phone_individual" 722 name="referral_phone" 723 class="form-input referral-phone-input" 724 placeholder="Referans Telefon Numarası" 725 maxlength="10" 726 pattern="[0-9]{10}" 727 value="" 728 autocomplete="off" 729 data-referral-preview="referral-phone-preview-indiv
729idual" 730 > 731 </div> 732 <div id="referral-phone-preview-individual" class="referral-phone-preview"></div> 733 </div> 734 735 <button type="button" class="btn" id="submit-btn-individual">Devam</button> 736 </div> 737 738 <!-- Adım 2: Resim Yükleme (Opsiyonel) - Bireysel --> 739 <div id="step-upload-media-individual" class="register-step media-upload-step " style="display: none;"> 740 <p style="color: var(--text-secondary); margin-bottom: 24px; font-size: 0.95rem;"> 741 Profil fotoÄrafı ve firma logosu yüklemek isteÄe baÄlıdır. İsterseniz bu adımı atlayabilirsiniz. 742 </p> 743 744 <div class="media-upload-section" style="text-align: center;"> 745 <h3 class="media-upload-title" style="text-align: center;">Profil FotoÄrafı (Opsiyonel)</h3> 746 <div class="avatar-upload-wrapper" style="text-align: center; margin-bottom: 16px;"> 747 <div class="profile-avatar" id="registerAvatarIndividual" style="width: 120px; height: 120px; font-size: 3rem; cursor: pointer; margin: 0 auto;" onclick="document.getElementById('avatarInputIndividual').click();"> 748 <span id="avatarInitialIndividual"> 749 <i class="fas fa-user" style="font-size: 2.5rem; opacity: 0.5;"></i> 750 </span> 751 <img id="avatarPreviewIndividual" alt="Avatar" style="display: none; width: 100%; height: 100%; object-fit: cover;"> 752 </div> 753 <label class="avatar-edit-btn" for="avatarInputIndividual" title="FotoÄraf Seç"> 754 <i class="fas fa-camera"></i> 755 </label> 756 <input type="file" id="avatarInputIndividual" name="avatar" accept="image/jpeg,image/png,image/gif,image/webp" style="display: none;"> 757 </div> 758 <div class="form-error" id="error-avatar_individual" style="display: none; text-align: center;"></div> 759 760 <p class="media-upload-hint" style="text-align: center;"> 761 <i class="fas fa-info-circle"></i> 762 JPEG, PNG, GIF veya WebP. Max 5MB 763 </p> 764 </div> 765 766 <div style="display: flex; gap: 12px; margin-top: 32px;"> 767 <button type="button" class="skip-button" id="skip-media-btn-individual">Atla</button> 768 <button type="button" class="btn" id="continue-media-btn-individual">Devam</button> 769 </div> 770 </div> 771 </form> 772 773 <!-- DanıÅman Form --> 774 <form method="post" action="/accounts/register/" enctype="multipart/form-data" id="form-consultant" style="display: none;"> 775 <input type="hidden" name="csrfmiddlewaretoken" value="2xg8q9AbyLEo0yB67DYqwtzSNqmTnnvKkOIpAfKv6P0pdiB03cg85F6ZPOqGSqps"> 776 <input type="hidden" name="member_type" value="consultant"> 777 778 <!-- Adım 1: Genel Bilgiler - DanıÅman --> 779 <div id="step-validate-info-consultant" class="register-step active" style="display: block;"> 780 <div class="form-group" style="display:none;" aria-hidden="true"> 781 <input type="hidden" name="consultant_type" id="consultant_type" value=""> 782 </div> 783 <p class="form-hint" style="margin-bottom: 1rem;">DanıÅman alt tipi baÄlandıÄınız firmanın türünden otomatik belirlenir.</p> 784 785 <!-- SPK Lisanslı: Lisans No (Firma Vergi No'dan önce) --> 786 <div class="form-group" id="consultant_license_wrapper" style="display: none;"> 787 <input type="text" id="consultant_license_no" name="consultant_license_no" 788 class="form-input " 789 placeholder="Lisans No *" value=""> 790 <div class="form-error" id="error-consultant_license_no_consultant" style="display: none;"></div> 791 792 </div> 793 794 <!-- Ad, Soyad - Yan yana --> 795 <div class="form-row"> 796 <div class="form-group form-group-half"> 797 <input 798 type="text" 799 id="first_name_consultant" 800 name="first_name" 801 class="form-input " 802 placeholder="Adınız *" 803 value="" 804 required 805 autocomplete="given-name" 806 > 807 <div class="form-error" id="error-first_name_consultant" style="display: none;"></div> 808 809 </div> 810 811 <div class="form-group form-group-half"> 812 <input 813 type="text" 814 id="last_name_consultant" 815 name="last_name" 816 class="form-input " 817 placeholder="Soyadınız *" 818 value="" 819 required 820 autocomplete="family-name" 821 > 822 <div class="form-error" id="error-last_name_consultant" style="display: none;"></div> 823 824 </div> 825 </div> 826 827 <!-- DanıÅman alanı: Firma seçimi (company_profile_id) --> 828 <div class="form-group"> 829 <input type="hidden" name="company_profile_id" id="company_profile_id" value=""> 830 <select id="company_profile_select" class="form-input" style="width: 100%;"> 831 <option value="">ÃalıÅtıÄınız firmayı seçin *</option> 832 833 </select> 834 <div class="form-error" id="error-company_profile_id_consultant" style="display: none;"></div> 835 836 </div> 837 838 <!-- Email --> 839 <div class="form-group"> 840 <input 841 type="email" 842 id="email_consultant" 843 name="email" 844 class="form-input " 845 placeholder="E-posta Adresi *" 846 value="" 847 required 848 autocomplete="email" 849 > 850 <div class="form-error" id="error-email_consultant" style="display: none;"></div> 851 852 </div> 853 854 <!-- Phone --> 855 <div class="form-group"> 856 <div class="phone-input-group">
857 <span class="phone-prefix">+90</span> 858 <input 859 type="tel" 860 id="phone_number_consultant" 861 name="phone_number" 862 class="form-input " 863 placeholder="Telefon Numarası" 864 maxlength="10" 865 pattern="[0-9]{10}" 866 value="" 867 autocomplete="tel" 868 > 869 </div> 870 <div class="form-hint" style="font-size: 0.75rem; margin-top: 4px; color: var(--text-secondary, #9ca3af);">Zorunlu deÄildir</div> 871 <div class="form-error" id="error-phone_number_consultant" style="display: none;"></div> 872 873 </div> 874 875 <!-- Password --> 876 <div class="form-row"> 877 <div class="form-group form-group-half"> 878 <input 879 type="password" 880 id="password_consultant" 881 name="password" 882 class="form-input " 883 placeholder="Åifre (En az 8 karakter, bir büyük harf) *" 884 minlength="8" required 885 autocomplete="new-password" 886 > 887 <ul class="password-rules" id="password-rules-consultant" aria-live="polite"> 888 <li class="password-rule is-fail" data-rule="minLength"><span class="password-rule__mark" aria-hidden="true">â</span> En az 8 karakter</li> 889 <li class="password-rule is-fail" data-rule="uppercase"><span class="password-rule__mark" aria-hidden="true">â</span> En az bir büyük harf</li> 890 </ul> 891 <div id="password-error-consultant" class="form-error" style="display: none;"></div> 892 893 </div> 894 895 <div class="form-group form-group-half"> 896 <input 897 type="password" 898 id="password_confirm_consultant" 899 name="password_confirm" 900 class="form-input " 901 placeholder="Åifre Tekrar *" 902 minlength="8" required 903 autocomplete="new-password" 904 > 905 <div id="password-match-error-consultant" class="form-error" style="display: none;"></div> 906 907 </div> 908 </div> 909 910 <!-- Adres (DanıÅman) --> 911 <div class="form-group" style="margin-top: 16px;"> 912 <label class="form-label" style="margin-bottom: 8px;">Adres</label> 913 <input type="hidden" name="city_id" id="reg_consultant_city_id" value=""> 914 <input type="hidden" name="district_id" id="reg_consultant_district_id" value=""> 915 <input type="hidden" name="quarter_id" id="reg_consultant_quarter_id" value=""> 916 <input type="hidden" name="quarter_value" id="reg_consultant_quarter_value" value=""> 917 <input type="hidden" name="city_name" id="reg_consultant_city_name" value=""> 918 <input type="hidden" name="district_name" id="reg_consultant_district_name" value=""> 919 <input type="hidden" name="quarter_name" id="reg_consultant_quarter_name" value=""> 920 <div class="form-row" style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; margin-bottom: 12px;"> 921 <select class="form-input" id="reg_consultant_il" style="width: 100%;"><option value="">İl Seçiniz</option></select> 922 <select class="form-input" id="reg_consultant_ilce" style="width: 100%;" disabled><option value="">İlçe Seçiniz</option></select> 923 <select class="form-input" id="reg_consultant_mahalle" style="width: 100%;" disabled><option value="">Mahalle Seçiniz</option></select> 924 </div> 925 <input type="text" name="street_and_number" class="form-input" placeholder="Sokak ve numara"> 926 </div> 927 928 <!-- Mezuniyet Bilgileri (DanıÅman) --> 929 <div class="graduation-section" id="graduation-section-consultant" style="display: block;"> 930 <div class="graduation-section-title"> 931 <i class="fas fa-graduation-cap"></i>
932 <span>Mezuniyet Bilgileri</span> 933 <span id="graduation-required-badge-consultant" class="graduation-required-badge" style="display: none;">* Zorunlu</span> 934 </div> 935 936 <div class="graduation-info-note" id="graduation-info-note-consultant"> 937 <i class="fas fa-info-circle"></i> 938 <span id="graduation-note-text-consultant">Mezuniyetiniz uygulama üzerinde uzmanlık puanınızı arttırır ve uygulamanın bir çok alanda size öncelik vermesini saÄlar.</span> 939 </div> 940 <div class="form-error" id="error-education_level_consultant" style="display: none;"></div> 941 942 <!-- Hidden fields for graduation data --> 943 <input type="hidden" name="education_level" id="education_level_consultant" value=""> 944 <input type="hidden" name="university_id" id="university_id_consultant" value=""> 945 <input type="hidden" name="department_id" id="department_id_consultant" value=""> 946 <input type="hidden" name="custom_department" id="custom_department_consultant" value=""> 947 <input type="hidden" name="skip_diploma" id="skip_diploma_consultant" value=""> 948 949 <!-- EÄitim Seviyesi Seçimi --> 950 <div class="education-level-options"> 951 <label class="education-level-option" data-level="0"> 952 <input type="radio" name="education_level_radio_consultant" value="0"> 953 <span>OrtaöÄretim (Lise)</span> 954 </label> 955 <label class="education-level-option" data-level="2"> 956 <input type="radio" name="education_level_radio_consultant" value="2"> 957 <span>Ãn Lisans</span> 958 </label> 959 <label class="education-level-option" data-level="1"> 960 <input type="radio" name="education_level_radio_consultant" value="1"> 961 <span>Lisans</span> 962 </label> 963 </div> 964 965 <!-- Ãniversite/Bölüm Alanları (Ãn Lisans/Lisans seçildiÄinde görünür) --> 966 <div id="higher-education-fields-consultant" class="higher-education-fields"> 967 <div class="form-group" style="margin-bottom: 12px;"> 968 <select class="form-input" id="university_select_consultant" style="width: 100%;"> 969 <option value="">Ãniversite Seçiniz *</option> 970 </select> 971 <div class="form-error" id="error-university_consultant" style="display: none;"></div> 972 </div> 973 974 <div class="form-group" style="margin-bottom: 12px;"> 975 <select class="form-input" id="department_select_consultant" style="width: 100%;"> 976 <option value="">Bölüm Seçiniz</option> 977 </select> 978 </div> 979 980 <div class="form-group" style="margin-bottom: 12px;"> 981 <input 982 type="text" 983 id="custom_department_input_consultant" 984 class="form-input" 985 placeholder="Bölümünüzü listede bulamadıysanız buraya yazın" 986 maxlength="255" 987 > 988 <div class="form-hint" style="font-size: 0.8rem; margin-top: 4px; color: var(--text-secondary);"> 989 Bölümünüz listede yoksa yukarıdaki alana yazabilirsiniz 990 </div> 991 </div> 992 993 <!-- Diploma/Belge Yükleme --> 994 <div class="diploma-upload-section"> 995 <p style="margin-bottom: 12px; font-size: 0.9rem; color: var(--text-secondary);"> 996 E-devlet mezuniyet belgesi veya diploma görseli yükleyebilirsiniz (opsiyonel) 997 </p> 998 <label for="diploma_file_consultant"> 999 <i class="fas fa-upload"></i>
1000 <span>Belge Seç</span> 1001 </label> 1002 <input type="file" id="diploma_file_consultant" name="diploma_file" accept="image/*,.pdf" style="display: none;"> 1003 <div id="diploma_preview_consultant" class="diploma-preview" style="display: none;"> 1004 <div class="file-name"> 1005 <i class="fas fa-check-circle"></i> 1006 <span id="diploma_filename_consultant"></span> 1007 </div> 1008 </div> 1009 1010 <div class="skip-diploma-option"> 1011 <input type="checkbox" id="skip_diploma_checkbox_consultant"> 1012 <label for="skip_diploma_checkbox_consultant">Bu adımı sonra yapabilirsiniz</label> 1013 </div> 1014 </div> 1015 </div> 1016 </div> 1017 1018 <div class="referral-phone-card"> 1019 <div class="referral-phone-card__header"> 1020 <span class="referral-phone-card__badge"><i class="fas fa-gift" aria-hidden="true"></i> Referans</span> 1021 <span class="referral-phone-card__optional">Zorunlu deÄildir</span> 1022 </div> 1023 <p class="referral-phone-card__lead"> 1024 Size referans olan üyemizin numarasını girin, 1025 <strong><span class="referral-phone-bonus-amount">5</span> kredi hediye</strong> kazanın. 1026 </p> 1027 <div class="phone-input-group"> 1028 <span class="phone-prefix">+90</span> 1029 <input 1030 type="tel" 1031 id="referral_phone_consultant" 1032 name="referral_phone" 1033 class="form-input referral-phone-input" 1034 placeholder="Referans Telefon Numarası" 1035 maxlength="10" 1036 pattern="[0-9]{10}" 1037 value="" 1038 autocomplete="off" 1039 data-referral-preview="referral-phone-preview-consultant" 1040 > 1041 </div> 1042 <div id="referral-phone-preview-consultant" class="referral-phone-preview"></div> 1043 </div> 1044 1045 <button type="button" class="btn" id="submit-btn-consultant">Devam</button> 1046 </div> 1047 1048 <!-- Adım 2: Resim Yükleme (Opsiyonel) - DanıÅman --> 1049 <div id="step-upload-media-consultant" class="register-step media-upload-step " style="display: none;"> 1050 <p style="color: var(--text-secondary); margin-bottom: 24px; font-size: 0.95rem;"> 1051 Profil fotoÄrafı yüklemek isteÄe baÄlıdır. İsterseniz bu adımı atlayabilirsiniz. 1052 </p> 1053 1054 <div class="media-upload-section" style="text-align: center;"> 1055 <h3 class="media-upload-title" style="text-align: center;">Profil FotoÄrafı (Opsiyonel)</h3> 1056 <div class="avatar-upload-wrapper" style="text-align: center; margin-bottom: 16px;"> 1057 <div class="profile-avatar" id="registerAvatarConsultant" style="width: 120px; height: 120px; font-size: 3rem; cursor: pointer; margin: 0 auto;" onclick="document.getElementById('avatarInputConsultant').click();"> 1058 <span id="avatarInitialConsultant"> 1059 <i class="fas fa-user" style="font-size: 2.5rem; opacity: 0.5;"></i> 1060 </span> 1061 <img id="avatarPreviewConsultant" alt="Avatar" style="display: none; width: 100%; height: 100%; object-fit: cover;"> 1062 </div> 1063 <label class="avatar-edit-btn" for="avatarInputConsultant" title="FotoÄraf Seç"> 1064 <i class="fas fa-camera"></i> 1065 </label> 1066 <input type="file" id="avatarInputConsultant" name="avatar" accept="image/jpeg,image/png,image/gif,image/webp" style="display: none;"> 1067 </div> 1068 <div class="form-error" id="error-avatar_consultant" style="display: none; text-align: center;"></div> 1069 1070 <p class="media-upload-hint" style="text-align: center;"> 1071 <i class="fas fa-info-circle"></i> 1072 JPEG, PNG, GIF veya WebP. Max 5MB 1073 </p> 1074 </div> 1075 1076 <div style="display: flex; gap: 12px; margin-top: 32px;"> 1077 <button type="button" class="skip-button" id="skip-media-btn-consultant">Atla</button> 1078 <button type="button" class="btn" id="continue-media-btn-consultant">Devam</button> 1079 </div> 1080 </div> 1081 1082 <!-- Adım 3: Uzmanlık Bölgeleri - DanıÅman --> 1083 <div id="step-expertise-areas-consultant" class="register-step " style="display: none;"> 1084 <!-- Expert firma: Ana Uzmanlık Bölgeleriniz (sadece il, max 5) --> 1085 <div id="expertise-consultant-spk" style="display: none;"> 1086 <h3 style="margin-bottom: 8px; font-size: 1.1rem;">Ana Uzmanlık Bölgeleriniz</h3> 1087 <p style="color: var(--text-secondary); margin-bottom: 20px; font-size: 0.9rem;"> 1088 Uzman olduÄunuz illeri seçin. En fazla <strong>5 il</strong> ekleyebilirsiniz. Adres iliniz ile eÅleÅen bölge <b>prime</b> olarak iÅaretlenir. 1089 </p> 1090 <input type="hidden" name="expertise_cities" id="expertise_cities_consultant" value=""> 1091 <div class="form-group" style="margin-bottom: 16px;"> 1092 <select class="form-input" id="expertise_il_only_consultant" style="width: 100%;"> 1093 <option value="">
1093İl Seçiniz (seçtiÄinizde listeye eklenir)</option> 1094 </select> 1095 </div> 1096 <div id="expertise-list-cities-consultant" style="margin-bottom: 20px;"> 1097 <div id="no-expertise-cities-msg-consultant" style="padding: 20px; text-align: center; color: var(--text-secondary); background: rgba(255,255,255,0.03); border-radius: 8px; border: 1px dashed rgba(255,255,255,0.15);"> 1098 <i class="fas fa-map-marker-alt" style="font-size: 20px; margin-bottom: 8px; opacity: 0.5;"></i> 1099 <div style="font-size: 0.9rem;">Henüz il seçmediniz</div> 1100 </div> 1101 </div> 1102 <div id="expertise-hint-cities-consultant" class="form-hint" style="display: none; margin-bottom: 16px; padding: 8px 12px; background: rgba(59, 130, 246, 0.1); border-radius: 6px; font-size: 0.85rem;"></div> 1103 </div> 1104 1105 <!-- Normal firma: Uzmanlık Bölgeleriniz (il-ilçe-mahalle, max 5) --> 1106 <div id="expertise-consultant-emlak" style="display: none;"> 1107 <h3 style="margin-bottom: 8px; font-size: 1.1rem;">Uzmanlık Bölgeleriniz</h3> 1108 <p style="color: var(--text-secondary); margin-bottom: 20px; font-size: 0.9rem;"> 1109 Uzman olduÄunuz bölgeleri seçin. En fazla <strong>5 mahalle</strong> ekleyebilirsiniz. 1110 </p> 1111 <input type="hidden" name="expertise_quarters" id="expertise_quarters_consultant" value=""> 1112 <div class="form-group" style="margin-bottom: 16px;"> 1113 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px;"> 1114 <select class="form-input" id="expertise_il_consultant" style="width: 100%;"> 1115 <option value="">İl Seçiniz</option> 1116 </select> 1117 <select class="form-input" id="expertise_ilce_consultant" style="width: 100%;" disabled> 1118 <option value="">İlçe Seçiniz</option> 1119 </select> 1120 </div> 1121 <select class="form-input" id="expertise_mahalle_consultant" style="width: 100%;" disabled> 1122 <option value="">Mahalle Seçiniz (seçtiÄinizde listeye eklenir)</option> 1123 </select> 1124 </div> 1125 <div id="expertise-list-consultant" style="margin-bottom: 20px;"> 1126 <div id="no-expertise-msg-consultant" style="padding: 20px; text-align: center; color: var(--text-secondary); background: rgba(255,255,255,0.03); border-radius: 8px; border: 1px dashed rgba(255,255,255,0.15);"> 1127 <i class="fas fa-map-marker-alt" style="font-size: 20px; margin-bottom: 8px; opacity: 0.5;"></i> 1128 <div style="font-size: 0.9rem;">Henüz bölge seçmediniz</div> 1129 </div> 1130 </div> 1131 <div id="expertise-hint-consultant" class="form-hint" style="display: none; margin-bottom: 16px; padding: 8px 12px; background: rgba(59, 130, 246, 0.1); border-radius: 6px; font-size: 0.85rem;"></div> 1132 </div> 1133 1134 <div style="display: flex; gap: 12px; margin-top: 24px;"> 1135 <button type="button" class="skip-button" id="skip-expertise-btn-consultant">Atla</button> 1136 <button type="button" class="btn" id="continue-expertise-btn-consultant">Devam</button> 1137 </div> 1138 </div> 1139 </form> 1140 1141 <!-- Kurumsal Form --> 1142 <form method="post" action="/accounts/register/" enctype="multipart/form-data" id="form-corporate" style="display: none;"> 1143 <input type="hidden" name="csrfmiddlewaretoken" value="2xg8q9AbyLEo0yB67DYqwtzSNqmTnnvKkOIpAfKv6P0pdiB03cg85F6ZPOqGSqps"> 1144 <input type="hidden" name="member_type" value="corporate"> 1145 1146 <!-- Adım 1: Genel Bilgiler - Kurumsal --> 1147 <div id="step-validate-info-corporate" class="register-step active" style="display: block;"> 1148 <!-- Ad, Soyad - Yan yana --> 1149 <div class="form-row"> 1150 <div class="form-group form-group-half"> 1151 <input 1152 type="text" 1153 id="first_name_corporate" 1154 name="first_name" 1155 class="form-input " 1156 placeholder="Adınız *" 1157 value="" 1158 required 1159 autocomplete="given-name" 1160 > 1161 <div class="form-error" id="error-first_name_corporate" style="display: none;"></div> 1162 1163 </div> 1164 1165 <div class="form-group form-group-half"> 1166 <input 1167 type="text" 1168 id="last_name_corporate" 1169 name="last_name" 1170 class="form-input " 1171 placeholder="Soyadınız *" 1172 value="" 1173 required 1174 autocomplete="family-name" 1175 > 1176 <div class="form-error" id="error-last_name_corporate" style="display: none;"></div> 1177 1178 </div> 1179 </div> 1180 1181 <!-- Kurumsal Alanlar --> 1182 <div class="form-group"> 1183 <input 1184 type="text" 1185 id="company_name" 1186 name="company_name" 1187 class="form-input " 1188 placeholder="Firma Marka/Ãnvan (opsiyonel)" 1189 value="" 1190 > 1191 1192 <div class="form-hint" style="font-size: 0.75rem; margin-top: 4px; color: var(--text-secondary, #9ca3af);">BoÅ bırakılırsa ad soyad kullanılır</div> 1193 1194 <div class="form-error" id="error-company_name" style="display: none;"></div> 1195 1196 </div> 1197 1198 <!-- Kurumsal Firma Tipi Seçimi --> 1199 <div class="form-group"> 1200 <div class="corporate-type-buttons"> 1201 <button type="button" class="corporate-type-btn active" data-type="emlak" id="corporate_type_emlak"> 1202 Emlak Firması 1203 </button> 1204 <button type="button" class="corporate-type-btn " data-type="spk" id="corporate_type_spk"> 1205 SPK Lisanslı DeÄerleme Firması 1206 </button> 1207 <button type="button" class="corporate-type-btn " data-type="lihkab" id="corporate_type_lihkab"> 1208 Lihkab Büro 1209 </button> 1210 </div> 1211 <input type="hidden" name="corporate_type" id="corporate_type" value="emlak"> 1212 <div class="form-error" id="error-corporate_type" style="display: none;"></div> 1213 1214 </div> 1215 1216 <!-- Emlak: yetki belge no (opsiyonel) | SPK: TC | Lihkab: büro no --> 1217 <div class="corporate-type-fields"> 1218 <div class="form-row" id="corporate_fields_row"> 1219 <!-- SPK: TC (sadece SPK seçiliyken görünür) --> 1220 <div class="form-group form-group-half" id="spk_tc_wrapper" style="display: none;"> 1221 <input type="text" id="spk_tc_no" name="spk_tc_no" 1222 class="form-input " 1223 placeholder="TC Kimlik No *" maxlength="11" value=""> 1224 <div class="form-error" id="error-spk_tc_no" style="display: none;"></div> 1225 1226 </div> 1227 <div class="form-group form-group-half" id="office_no_wrapper" style="display: none;"> 1228 <input type="text" id="office_no_corporate" name="office_no" 1229 class="form-input " 1230 placeholder="Büro No (opsiyonel)" value=""> 1231 <div class="form-error" id="error-office_no_corporate" style="display: none;"></div> 1232 1233 </div> 1234 <div class="form-group form-group-half"> 1235 <input type="text" id="company_license_no" name="company_license_no" 1236 class="form-input " 1237 placeholder="7 haneli yetki belge no (opsiyonel)" value=""> 1238 <div class="form-error" id="error-company_license_no" style="display: none;"></div> 1239 1240 </div> 1241 </div> 1242 </div> 1243 1244 <!-- Email --> 1245 <div class="form-group"> 1246 <input 1247 type="email" 1248 id="email_corporate" 1249 name="email" 1250 class="form-input " 1251 placeholder="E-posta Adresi *" 1252 value="" 1253 required 1254 autocomplete="email" 1255 > 1256 <div class="form-error" id="error-email_corporate" style="display: none;"></div> 1257 1258 </div> 1259 1260 <!-- Phone --> 1261 <div class="form-group"> 1262 <div class="phone-input-group">
1263 <span class="phone-prefix">+90</span> 1264 <input 1265 type="tel" 1266 id="phone_number_corporate" 1267 name="phone_number" 1268 class="form-input " 1269 placeholder="Telefon Numarası" 1270 maxlength="10" 1271 pattern="[0-9]{10}" 1272 value="" 1273 autocomplete="tel" 1274 > 1275 </div> 1276 <div class="form-hint" style="font-size: 0.75rem; margin-top: 4px; color: var(--text-secondary, #9ca3af);">Zorunlu deÄildir</div> 1277 <div class="form-error" id="error-phone_number_corporate" style="display: none;"></div> 1278 1279 </div> 1280 1281 <!-- Password --> 1282 <div class="form-row"> 1283 <div class="form-group form-group-half"> 1284 <input 1285 type="password" 1286 id="password_corporate" 1287 name="password" 1288 class="form-input " 1289 placeholder="Åifre (En az 8 karakter, bir büyük harf) *" 1290 minlength="8" required 1291 autocomplete="new-password" 1292 > 1293 <ul class="password-rules" id="password-rules-corporate" aria-live="polite"> 1294 <li class="password-rule is-fail" data-rule="minLength"><span class="password-rule__mark" aria-hidden="true">â</span> En az 8 karakter</li> 1295 <li class="password-rule is-fail" data-rule="uppercase"><span class="password-rule__mark" aria-hidden="true">â</span> En az bir büyük harf</li> 1296 </ul> 1297 <div id="password-error-corporate" class="form-error" style="display: none;"></div> 1298 1299 </div> 1300 1301 <div class="form-group form-group-half"> 1302 <input 1303 type="password" 1304 id="password_confirm_corporate" 1305 name="password_confirm" 1306 class="form-input " 1307 placeholder="Åifre Tekrar *" 1308 minlength="8" required 1309 autocomplete="new-password" 1310 > 1311 <div id="password-match-error-corporate" class="form-error" style="display: none;"></div> 1312 1313 </div> 1314 </div> 1315 1316 <!-- Adres (Kurumsal) --> 1317 <div class="form-group" style="margin-top: 16px;"> 1318 <label class="form-label" style="margin-bottom: 8px;">Adres</label> 1319 <input type="hidden" name="city_id" id="reg_corporate_city_id" value=""> 1320 <input type="hidden" name="district_id" id="reg_corporate_district_id" value=""> 1321 <input type="hidden" name="quarter_id" id="reg_corporate_quarter_id" value=""> 1322 <input type="hidden" name="quarter_value" id="reg_corporate_quarter_value" value=""> 1323 <input type="hidden" name="city_name" id="reg_corporate_city_name" value=""> 1324 <input type="hidden" name="district_name" id="reg_corporate_district_name" value=""> 1325 <input type="hidden" name="quarter_name" id="reg_corporate_quarter_name" value=""> 1326 <div class="form-row" style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; margin-bottom: 12px;"> 1327 <select class="form-input" id="reg_corporate_il" style="width: 100%;"><option value="">İl Seçiniz</option></select> 1328 <select class="form-input" id="reg_corporate_ilce" style="width: 100%;" disabled><option value="">İlçe Seçiniz</option></select> 1329 <select class="form-input" id="reg_corporate_mahalle" style="width: 100%;" disabled><option value="">Mahalle Seçiniz</option></select> 1330 </div> 1331 <input type="text" name="street_and_number" class="form-input" placeholder="Sokak ve numara"> 1332 </div> 1333 1334 <!-- Mezuniyet Bilgileri (Kurumsal) - SPK seçiliyse zorunlu --> 1335 <div class="graduation-section" id="graduation-section-corporate" style="display: block;"> 1336 <div class="graduation-section-title"> 1337 <i class="fas fa-graduation-cap"></i>
1338 <span>Mezuniyet Bilgileri</span> 1339 <span id="graduation-required-badge-corporate" class="graduation-required-badge" style="display: none;">* Zorunlu</span> 1340 </div> 1341 1342 <div class="graduation-info-note" id="graduation-info-note-corporate"> 1343 <i class="fas fa-info-circle"></i> 1344 <span id="graduation-note-text-corporate">Mezuniyetiniz uygulama üzerinde uzmanlık puanınızı arttırır ve uygulamanın bir çok alanda size öncelik vermesini saÄlar.</span> 1345 </div> 1346 <div class="form-error" id="error-education_level_corporate" style="display: none;"></div> 1347 1348 <!-- Hidden fields for graduation data --> 1349 <input type="hidden" name="education_level" id="education_level_corporate" value=""> 1350 <input type="hidden" name="university_id" id="university_id_corporate" value=""> 1351 <input type="hidden" name="department_id" id="department_id_corporate" value=""> 1352 <input type="hidden" name="custom_department" id="custom_department_corporate" value=""> 1353 <input type="hidden" name="skip_diploma" id="skip_diploma_corporate" value=""> 1354 1355 <!-- EÄitim Seviyesi Seçimi --> 1356 <div class="education-level-options"> 1357 <label class="education-level-option" data-level="0"> 1358 <input type="radio" name="education_level_radio_corporate" value="0"> 1359 <span>OrtaöÄretim (Lise)</span> 1360 </label> 1361 <label class="education-level-option" data-level="2"> 1362 <input type="radio" name="education_level_radio_corporate" value="2"> 1363 <span>Ãn Lisans</span> 1364 </label> 1365 <label class="education-level-option" data-level="1"> 1366 <input type="radio" name="education_level_radio_corporate" value="1"> 1367 <span>Lisans</span> 1368 </label> 1369 </div> 1370 1371 <!-- Ãniversite/Bölüm Alanları (Ãn Lisans/Lisans seçildiÄinde görünür) --> 1372 <div id="higher-education-fields-corporate" class="higher-education-fields"> 1373 <div class="form-group" style="margin-bottom: 12px;"> 1374 <select class="form-input" id="university_select_corporate" style="width: 100%;"> 1375 <option value="">Ãniversite Seçiniz *</option> 1376 </select> 1377 <div class="form-error" id="error-university_corporate" style="display: none;"></div> 1378 </div> 1379 1380 <div class="form-group" style="margin-bottom: 12px;"> 1381 <select class="form-input" id="department_select_corporate" style="width: 100%;"> 1382 <option value="">Bölüm Seçiniz</option> 1383 </select> 1384 </div> 1385 1386 <div class="form-group" style="margin-bottom: 12px;"> 1387 <input 1388 type="text" 1389 id="custom_department_input_corporate" 1390 class="form-input" 1391 placeholder="Bölümünüzü listede bulamadıysanız buraya yazın" 1392 maxlength="255" 1393 > 1394 <div class="form-hint" style="font-size: 0.8rem; margin-top: 4px; color: var(--text-secondary);"> 1395 Bölümünüz listede yoksa yukarıdaki alana yazabilirsiniz 1396 </div> 1397 </div> 1398 1399 <!-- Diploma/Belge Yükleme --> 1400 <div class="diploma-upload-section"> 1401 <p style="margin-bottom: 12px; font-size: 0.9rem; color: var(--text-secondary);"> 1402 E-devlet mezuniyet belgesi veya diploma görseli yükleyebilirsiniz (opsiyonel) 1403 </p> 1404 <label for="diploma_file_corporate"> 1405 <i class="fas fa-upload"></i>
1406 <span>Belge Seç</span> 1407 </label> 1408 <input type="file" id="diploma_file_corporate" name="diploma_file" accept="image/*,.pdf" style="display: none;"> 1409 <div id="diploma_preview_corporate" class="diploma-preview" style="display: none;"> 1410 <div class="file-name"> 1411 <i class="fas fa-check-circle"></i> 1412 <span id="diploma_filename_corporate"></span> 1413 </div> 1414 </div> 1415 1416 <div class="skip-diploma-option"> 1417 <input type="checkbox" id="skip_diploma_checkbox_corporate"> 1418 <label for="skip_diploma_checkbox_corporate">Bu adımı sonra yapabilirsiniz</label> 1419 </div> 1420 </div> 1421 </div> 1422 </div> 1423 1424 <div class="referral-phone-card"> 1425 <div class="referral-phone-card__header"> 1426 <span class="referral-phone-card__badge"><i class="fas fa-gift" aria-hidden="true"></i> Referans</span> 1427 <span class="referral-phone-card__optional">Zorunlu deÄildir</span> 1428 </div> 1429 <p class="referral-phone-card__lead"> 1430 Size referans olan üyemizin numarasını girin, 1431 <strong><span class="referral-phone-bonus-amount">5</span> kredi hediye</strong> kazanın. 1432 </p> 1433 <div class="phone-input-group"> 1434 <span class="phone-prefix">+90</span> 1435 <input 1436 type="tel" 1437 id="referral_phone_corporate" 1438 name="referral_phone" 1439 class="form-input referral-phone-input" 1440 placeholder="Referans Telefon Numarası" 1441 maxlength="10" 1442 pattern="[0-9]{10}" 1443 value="" 1444 autocomplete="off" 1445 data-referral-preview="referral-phone-preview-corporate" 1446 > 1447 </div> 1448 <div id="referral-phone-preview-corporate" class="referral-phone-preview"></div> 1449 </div> 1450 1451 <button type="button" class="btn" id="submit-btn-corporate">Devam</button> 1452 </div> 1453 1454 <!-- Adım 2: Resim/Logo Yükleme (Opsiyonel) - Kurumsal --> 1455 <div id="step-upload-media-corporate" class="register-step media-upload-step " style="display: none;"> 1456 <p style="color: var(--text-secondary); margin-bottom: 24px; font-size: 0.95rem;"> 1457 Profil fotoÄrafı ve firma logosu yüklemek isteÄe baÄlıdır. İsterseniz bu adımı atlayabilirsiniz. 1458 </p> 1459 1460 <div class="media-upload-section" style="text-align: center;"> 1461 <h3 class="media-upload-title" style="text-align: center;">Profil FotoÄrafı (Opsiyonel)</h3> 1462 <div class="avatar-upload-wrapper" style="text-align: center; margin-bottom: 16px;"> 1463 <div class="profile-avatar" id="registerAvatarCorporate" style="width: 120px; height: 120px; font-size: 3rem; cursor: pointer; margin: 0 auto;" onclick="document.getElementById('avatarInputCorporate').click();"> 1464 <span id="avatarInitialCorporate"> 1465 <i class="fas fa-user" style="font-size: 2.5rem; opacity: 0.5;"></i> 1466 </span> 1467 <img id="avatarPreviewCorporate" alt="Avatar" style="display: none; width: 100%; height: 100%; object-fit: cover;"> 1468 </div> 1469 <label class="avatar-edit-btn" for="avatarInputCorporate" title="FotoÄraf Seç"> 1470 <i class="fas fa-camera"></i> 1471 </label> 1472 <input type="file" id="avatarInputCorporate" name="avatar" accept="image/jpeg,image/png,image/gif,image/webp" style="display: none;"> 1473 </div> 1474 <div class="form-error" id="error-avatar_corporate" style="display: none; text-align: center;"></div> 1475 1476 <p class="media-upload-hint" style="text-align: center;"> 1477 <i class="fas fa-info-circle"></i> 1478 JPEG, PNG, GIF veya WebP. Max 5MB 1479 </p> 1480 </div> 1481 1482 <div class="media-upload-section"> 1483 <h3 class="media-upload-title">Firma Logosu (Opsiyonel)</h3> 1484 <div class="logo-preview-wrapper" style="text-align: center; margin-bottom: 16px;"> 1485 <div class="logo-preview" id="logoPreviewCorporate" style="margin: 0 auto; width: 200px; height: 120px;"> 1486 <div class="logo-placeholder" id="logoPlaceholderCorporate"> 1487 <i class="fas fa-building" style="font-size: 3rem; color: var(--muted);"></i>
1488 <span>Logo Yükle</span> 1489 </div> 1490 <img id="logoPreviewImgCorporate" alt="Logo" style="display: none; max-width: 100%; max-height: 100%; object-fit: contain;"> 1491 </div> 1492 <label for="logoInputCorporate" class="btn btn-secondary" style="margin-top: 12px; display: inline-block; width: auto; padding: 10px 20px;"> 1493 <i class="fas fa-upload"></i> Logo Seç 1494 </label> 1495 <input type="file" id="logoInputCorporate" name="company_logo" accept="image/jpeg,image/png,image/gif,image/webp" style="display: none;"> 1496 </div> 1497 <div class="form-error" id="error-company_logo" style="display: none;"></div> 1498 1499 <p class="media-upload-hint"> 1500 <i class="fas fa-info-circle"></i> 1501 JPEG, PNG, GIF veya WebP. Max 5MB 1502 </p> 1503 </div> 1504 1505 <div style="display: flex; gap: 12px; margin-top: 32px;"> 1506 <button type="button" class="skip-button" id="skip-media-btn-corporate">Atla</button> 1507 <button type="button" class="btn" id="continue-media-btn-corporate">Devam</button> 1508 </div> 1509 </div> 1510 1511 <!-- Adım 3: Uzmanlık Bölgeleri - Kurumsal --> 1512 <div id="step-expertise-areas-corporate" class="register-step " style="display: none;"> 1513 <!-- SPK: Ana Uzmanlık Bölgeleriniz (sadece il, max 5) --> 1514 <div id="expertise-corporate-spk" style="display: none;"> 1515 <h3 style="margin-bottom: 8px; font-size: 1.1rem;">Ana Uzmanlık Bölgeleriniz</h3> 1516 <p style="color: var(--text-secondary); margin-bottom: 20px; font-size: 0.9rem;"> 1517 Uzman olduÄunuz illeri seçin. En fazla <strong>5 il</strong> ekleyebilirsiniz. Adres iliniz ile eÅleÅen bölge <b>prime</b> olarak iÅaretlenir. 1518 </p> 1519 <input type="hidden" name="expertise_cities" id="expertise_cities_corporate" value=""> 1520 <div class="form-group" style="margin-bottom: 16px;"> 1521 <select class="form-input" id="expertise_il_only_corporate" style="width: 100%;"> 1522 <option value="">İl Seçiniz (seçtiÄinizde listeye eklenir)</option> 1523 </select> 1524 </div> 1525 <div id="expertise-list-cities-corporate" style="margin-bottom: 20px;"> 1526 <div id="no-expertise-cities-msg-corporate" style="padding: 20px; text-align: center; color: var(--text-secondary); background: rgba(255,255,255,0.03); border-radius: 8px; border: 1px dashed rgba(255,255,255,0.15);"> 1527 <i class="fas fa-map-marker-alt" style="font-size: 20px; margin-bottom: 8px; opacity: 0.5;"></i> 1528 <div style="font-size: 0.9rem;">Henüz il seçmediniz</div> 1529 </div> 1530 </div> 1531 <div id="expertise-hint-cities-corporate" class="form-hint" style="display: none; margin-bottom: 16px; padding: 8px 12px; background: rgba(59, 130, 246, 0.1); border-radius: 6px; font-size: 0.85rem;"></div> 1532 </div> 1533 1534 <!-- Emlak: Uzmanlık Bölgeleriniz (il-ilçe-mahalle, max 5) --> 1535 <div id="expertise-corporate-emlak" style="display: none;"> 1536 <h3 style="margin-bottom: 8px; font-size: 1.1rem;">Uzmanlık Bölgeleriniz</h3> 1537 <p style="color: var(--text-secondary); margin-bottom: 20px; font-size: 0.9rem;"> 1538 Uzman olduÄunuz bölgeleri seçin. En fazla <strong>5 mahalle</strong> ekleyebilirsiniz. 1539 </p> 1540 <input type="hidden" name="expertise_quarters" id="expertise_quarters_corporate" value=""> 1541 <div class="form-group" style="margin-bottom: 16px;"> 1542 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px;"> 1543 <select class="form-input" id="expertise_il_corporate" style="width: 100%;"> 1544 <option value="">
1544İl Seçiniz</option> 1545 </select> 1546 <select class="form-input" id="expertise_ilce_corporate" style="width: 100%;" disabled> 1547 <option value="">İlçe Seçiniz</option> 1548 </select> 1549 </div> 1550 <select class="form-input" id="expertise_mahalle_corporate" style="width: 100%;" disabled> 1551 <option value="">Mahalle Seçiniz (seçtiÄinizde listeye eklenir)</option> 1552 </select> 1553 </div> 1554 <div id="expertise-list-corporate" style="margin-bottom: 20px;"> 1555 <div id="no-expertise-msg-corporate" style="padding: 20px; text-align: center; color: var(--text-secondary); background: rgba(255,255,255,0.03); border-radius: 8px; border: 1px dashed rgba(255,255,255,0.15);"> 1556 <i class="fas fa-map-marker-alt" style="font-size: 20px; margin-bottom: 8px; opacity: 0.5;"></i> 1557 <div style="font-size: 0.9rem;">Henüz bölge seçmediniz</div> 1558 </div> 1559 </div> 1560 <div id="expertise-hint-corporate" class="form-hint" style="display: none; margin-bottom: 16px; padding: 8px 12px; background: rgba(59, 130, 246, 0.1); border-radius: 6px; font-size: 0.85rem;"></div> 1561 </div> 1562 1563 <div style="display: flex; gap: 12px; margin-top: 24px;"> 1564 <button type="button" class="skip-button" id="skip-expertise-btn-corporate">Atla</button> 1565 <button type="button" class="btn" id="continue-expertise-btn-corporate">Devam</button> 1566 </div> 1567 </div> 1568 </form> 1569 1570 </div><!-- #register-form-area --> 1571 1572</div> 1573 1574 1575<!-- OTP Modal --> 1576<div class="otp-modal-overlay" id="otpModal"> 1577 <div class="otp-modal"> 1578 <div class="otp-modal-header"> 1579 <h2 class="otp-modal-title">DoÄrulama Kodu</h2> 1580 <p class="otp-modal-subtitle">Telefonunuza gönderilen 6 haneli kodu girin</p> 1581 </div> 1582 1583 <div class="otp-phone-display" id="otpPhoneDisplay"> 1584 **** 1585 </div> 1586 1587 <form method="post" action="/accounts/register/" id="otp-form"> 1588 <input type="hidden" name="csrfmiddlewaretoken" value="2xg8q9AbyLEo0yB67DYqwtzSNqmTnnvKkOIpAfKv6P0pdiB03cg85F6ZPOqGSqps"> 1589 <input type="hidden" name="step" value="verify_otp"> 1590 <input type="hidden" name="member_type" id="otp_member_type" value="individual"> 1591 <input type="hidden" name="first_name" id="otp_first_name" value=""> 1592 <input type="hidden" name="last_name" id="otp_last_name" value=""> 1593 <input type="hidden" name="email" id="otp_email" value=""> 1594 <input type="hidden" name="phone_number" id="otp_phone_number" value=""> 1595 <input type="hidden" name="password" id="otp_password" value=""> 1596 <input type="hidden" name="password_confirm" id="otp_password_confirm" value=""> 1597 <!-- Kurumsal alanlar: Her zaman DOM'da olsun, AJAX ile açıldıÄında JS ile doldurulacak --> 1598 <input type="hidden" name="company_name" id="otp_company_name" value=""> 1599 <input type="hidden" name="corporate_type" id="otp_corporate_type" value="emlak"> 1600 <input type="hidden" name="company_license_no" id="otp_company_license_no" value=""> 1601 <input type="hidden" name="office_no" id="otp_office_no" value=""> 1602 <input type="hidden" name="spk_tc_no" id="otp_spk_tc_no" value=""> 1603 <!-- DanıÅman alanları --> 1604 <input type="hidden" name="consultant_type" id="otp_consultant_type" value="emlak"> 1605 <input type="hidden" name="consultant_license_no" id="otp_consultant_license_no" value=""> 1606 <input type="hidden" name="company_profile_id" id="otp_company_profile_id" value=""> 1607 <input type="hidden" name="expertise_quarters" id="otp_expertise_quarters" value=""> 1608 <input type="hidden" name="expertise_cities" id="otp_expertise_cities" value=""> 1609 <input type="hidden" name="city_id" id="otp_city_id" value=""> 1610 <input type="hidden" name="district_id" id="otp_district_id" value=""> 1611 <input type="hidden" name="quarter_id" id="otp_quarter_id" value=""> 1612 <input type="hidden" name="quarter_value" id="otp_quarter_value" value=""> 1613 <input type="hidden" name="city_name" id="otp_city_name" value=""> 1614 <input type="hidden" name="district_name" id="otp_district_name" value=""> 1615 <input type="hidden" name="quarter_name" id="otp_quarter_name" value=""> 1616 <input type="hidden" name="street_and_number" id="otp_street_and_number" value=""> 1617 <input type="hidden" name="referral_phone" id="otp_referral_phone" value=""> 1618
1619 <div class="otp-input-group" id="otpInputGroup"> 1620 <input type="text" class="otp-input" maxlength="1" pattern="[0-9]" inputmode="numeric" autocomplete="off" data-index="0"> 1621 <input type="text" class="otp-input" maxlength="1" pattern="[0-9]" inputmode="numeric" autocomplete="off" data-index="1"> 1622 <input type="text" class="otp-input" maxlength="1" pattern="[0-9]" inputmode="numeric" autocomplete="off" data-index="2"> 1623 <input type="text" class="otp-input" maxlength="1" pattern="[0-9]" inputmode="numeric" autocomplete="off" data-index="3"> 1624 <input type="text" class="otp-input" maxlength="1" pattern="[0-9]" inputmode="numeric" autocomplete="off" data-index="4"> 1625 <input type="text" class="otp-input" maxlength="1" pattern="[0-9]" inputmode="numeric" autocomplete="off" data-index="5"> 1626 </div> 1627 <input type="hidden" name="otp" id="otpValue" value=""> 1628 1629 <div id="otpError" class="form-error" style="text-align: center; margin-bottom: 16px; display: none;"></div> 1630 1631 <div class="otp-actions"> 1632 <button type="submit" class="btn" id="otp-verify-btn">DoÄrula ve Kayıt Ol</button> 1633 </div> 1634 1635 <div class="otp-resend"> 1636 <button type="button" id="otp-resend-btn" disabled> 1637 Tekrar Gönder 1638 </button> 1639 <div class="otp-timer" id="otpTimer"></div> 1640 </div> 1641 </form> 1642 </div> 1643</div> 1644 1645
1646<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
vendor: 1 bytes, line 1646
1646
1647<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/select2.min.js"></script>
vendor: 1 bytes, line 1647
1647
1648<script> 1649const PP_REGISTER_SUBMIT_URL = '/accounts/register/'; 1650const PP_ADMIN_REGISTER_MODE = false; 1651const PP_SKIP_SMS_VERIFICATION = false; 1652const adminMode = PP_ADMIN_REGISTER_MODE; 1653 1654document.addEventListener('DOMContentLoaded', function() { 1655 function applyAdminRegisterModeUi() { 1656 if (!adminMode) return; 1657 ['consultant', 'corporate'].forEach(function(formType) { 1658 const graduation = document.getElementById('graduation-section-' + formType); 1659 if (graduation) graduation.style.display = 'none'; 1660 const ilSelect = document.getElementById('reg_' + formType + '_il'); 1661 if (ilSelect) { 1662 const addressGroup = ilSelect.closest('.form-group'); 1663 if (addressGroup) addressGroup.style.display = 'none'; 1664 } 1665 }); 1666 const emailIds = ['email_individual', 'email_consultant', 'email_corporate']; 1667 document.querySelectorAll('.pp-auth-legacy-register input, .pp-auth-legacy-register select, .pp-auth-legacy-register textarea').forEach(function(el) { 1668 if (emailIds.indexOf(el.id) !== -1) { 1669 el.required = true; 1670 return; 1671 } 1672 el.removeAttribute('required'); 1673 el.removeAttribute('minlength'); 1674 }); 1675 const corpNote = document.querySelector('.auth-register-corporate-note'); 1676 if (corpNote) corpNote.style.display = 'none'; 1677 } 1678 applyAdminRegisterModeUi(); 1679 1680 function adminValidateEmailOnly(form, formType) { 1681 const emailInput = form.querySelector('input[name="email"]'); 1682 const emailVal = (emailInput && emailInput.value) ? emailInput.value.trim() : ''; 1683 const errorId = 'error-email_' + formType; 1684 const errorDiv = document.getElementById(errorId); 1685 if (!emailVal) { 1686 if (errorDiv) { 1687 errorDiv.textContent = 'E-posta adresi gereklidir'; 1688 errorDiv.style.display = 'block'; 1689 } 1690 if (emailInput) { 1691 emailInput.classList.add('error'); 1692 emailInput.focus(); 1693 } 1694 return false; 1695 } 1696 const emailOk = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailVal); 1697 if (!emailOk) { 1698 if (errorDiv) { 1699 errorDiv.textContent = 'Geçerli bir e-posta adresi girin'; 1700 errorDiv.style.display = 'block'; 1701 } 1702 if (emailInput) { 1703 emailInput.classList.add('error'); 1704 emailInput.focus(); 1705 } 1706 return false; 1707 } 1708 if (errorDiv) { 1709 errorDiv.style.display = 'none'; 1710 errorDiv.textContent = ''; 1711 } 1712 if (emailInput) emailInput.classList.remove('error'); 1713 return true; 1714 } 1715 1716 function notifyAdminRegisterStep(step) { 1717 if (!adminMode) return; 1718 if (typeof window.updateAdminRegisterStepper === 'function') { 1719 window.updateAdminRegisterStepper(step); 1720 } 1721 document.dispatchEvent(new CustomEvent('adminRegisterStepChange', { detail: { step: step } })); 1722 } 1723 function shouldSkipExpertiseStep(formType) { 1724 if (adminMode) return true; 1725 if (formType === 'corporate') { 1726 return (document.getElementById('corporate_type') || {}).value === 'lihkab'; 1727 } 1728 if (formType === 'consultant') { 1729 return (document.getElementById('consultant_type') || {}).value === 'lihkab'; 1730 } 1731 return false; 1732 } 1733 1734 function finalizeRegistrationFromMediaStep(event, formType, buttonId) { 1735 handleFormSubmit(event, 'upload_media', buttonId, formType); 1736 } 1737 1738 function finalizeRegistrationAfterExpertise(formType) { 1739 const step = adminMode ? 'upload_media' : 'send_otp'; 1740 handleFormSubmit(new Event('click'), step, 'continue-expertise-btn-' + formType, formType); 1741 } 1742 // ========== AJAX Form Submission Functions ========== 1743 1744 // Saved form data for OTP modal 1745 let savedFormData = null; 1746 1747 // Get registration form for a member type (prefer explicit formType over tab state) 1748 function getFormByType(formType) { 1749 if (formType === 'corporate' || formType === 'consultant' || formType === 'individual') { 1750 return document.getElementById('form-' + formType); 1751 } 1752 return null; 1753 } 1754 1755 function syncMemberTypeInput(formType) { 1756 const memberTypeInput = document.getElementById('member_type'); 1757 if (memberTypeInput && formType) { 1758 memberTypeInput.value = formType; 1759 } 1760 } 1761 1762 // Get active form based on member type 1763 function getActiveForm() { 1764 const memberType = document.getElementById('member_type').value; 1765 return getFormByType(memberType) || document.getElementById('form-individual'); 1766 } 1767 1768 // Get active member type 1769 function getActiveMemberType() { 1770 return document.getElementById('member_type').value; 1771 } 1772 1773 function formatFieldErrorMessage(message) { 1774 if (Array.isArray(message)) { 1775 return message.filter(Boolean).join(' '); 1776 } 1777 if (message && typeof message === 'object') {
1778 return Object.values(message).flat().filter(Boolean).join(' '); 1779 } 1780 return String(message || ''); 1781 } 1782 1783 function resolveFieldErrorElement(fieldName, formType) { 1784 const candidates = [ 1785 'error-' + fieldName + '_' + formType, 1786 'error-' + fieldName, 1787 ]; 1788 if (fieldName === 'password') { 1789 candidates.unshift('password-error-' + formType); 1790 } 1791 if (fieldName === 'password_confirm') { 1792 candidates.unshift('password-match-error-' + formType); 1793 } 1794 for (let i = 0; i < candidates.length; i += 1) { 1795 const el = document.getElementById(candidates[i]); 1796 if (el) return el; 1797 } 1798 return null; 1799 } 1800 1801 function resolveFieldInputElement(fieldName, formType) { 1802 const candidates = [fieldName + '_' + formType, fieldName]; 1803 for (let i = 0; i < candidates.length; i += 1) { 1804 const el = document.getElementById(candidates[i]); 1805 if (el) return el; 1806 } 1807 const form = getFormByType(formType); 1808 if (form) { 1809 const byName = form.querySelector('[name="' + fieldName + '"]'); 1810 if (byName) return byName; 1811 } 1812 return null; 1813 } 1814 1815 // Show loading state 1816 function showLoading(buttonId) { 1817 const btn = document.getElementById(buttonId); 1818 if (btn) { 1819 btn.disabled = true; 1820 const originalText = btn.textContent; 1821 btn.dataset.originalText = originalText; 1822 btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Gönderiliyor...'; 1823 } 1824 } 1825 1826 // Hide loading state 1827 function hideLoading(buttonId) { 1828 const btn = document.getElementById(buttonId); 1829 if (btn) { 1830 btn.disabled = false; 1831 btn.textContent = btn.dataset.originalText || 'Devam'; 1832 } 1833 } 1834 1835 // Show field error 1836 function showFieldError(fieldName, message, formType) { 1837 const text = formatFieldErrorMessage(message); 1838 const errorDiv = resolveFieldErrorElement(fieldName, formType); 1839 if (errorDiv) { 1840 errorDiv.textContent = text; 1841 errorDiv.style.display = 'block'; 1842 } 1843 1844 const input = resolveFieldInputElement(fieldName, formType); 1845 if (input) { 1846 input.classList.add('error'); 1847 } 1848 } 1849 1850 // Clear all field errors 1851 function clearFieldErrors(formType) { 1852 const form = getFormByType(formType) || getActiveForm(); 1853 if (!form) return; 1854 const errorDivs = form.querySelectorAll('.form-error'); 1855 errorDivs.forEach(div => { 1856 if (div.id && div.id.startsWith('error-')) { 1857 div.style.display = 'none'; 1858 div.textContent = ''; 1859 } 1860 }); 1861 1862 const inputs = form.querySelectorAll('.form-input'); 1863 inputs.forEach(input => input.classList.remove('error')); 1864 } 1865 1866 // Show registration exists warning 1867 function showRegistrationExistsWarning(response) { 1868 const warningDiv = document.querySelector('.registration-warning'); 1869 if (warningDiv) { 1870 warningDiv.style.display = 'block'; 1871 } 1872 } 1873 1874 // AJAX submit function 1875 async function submitFormAjax(form, step) { 1876 const formData = new FormData(form); 1877 formData.append('step', step); 1878 1879 const response = await fetch('/accounts/register/', { 1880 method: 'POST', 1881 body: formData, 1882 headers: { 1883 'X-Requested-With': 'XMLHttpRequest', 1884 }, 1885 credentials: 'same-origin' 1886 }); 1887 1888 if (!response.ok) { 1889 if (response.status === 500) { 1890 throw new Error('Sunucu hatası. Lütfen daha sonra tekrar deneyin.'); 1891 } 1892 throw new Error(`HTTP error! status: ${response.status}`); 1893 } 1894 1895 let data; 1896 try { 1897 data = await response.json(); 1898 } catch (e) { 1899 throw new Error('Sunucudan geçersiz yanıt alındı.'); 1900 } 1901 1902 return data; 1903 } 1904 1905 // Handle success response 1906 function handleSuccess(response, currentStep, formType) { 1907 switch (response.step) { 1908 case 'upload_media': 1909 showUploadMediaStep(formType); 1910 break; 1911 case 'send_otp': 1912 // Save form data for OTP 1913 const form = getActiveForm(); 1914 savedFormData = new FormData(form); 1915 showOTPModal(response); 1916 break; 1917 case 'complete': 1918 window.location.href = response.redirect_url || '/'; 1919 break; 1920 } 1921 } 1922 1923 // Handle errors 1924 function handleErrors(response, formType) { 1925 clearFieldErrors(formType); 1926 1927 let fallbackMessage = ''; 1928 if (response.errors) {
1929 Object.keys(response.errors).forEach(function(fieldName) { 1930 showFieldError(fieldName, response.errors[fieldName], formType); 1931 if (!resolveFieldErrorElement(fieldName, formType) && !fallbackMessage) { 1932 fallbackMessage = formatFieldErrorMessage(response.errors[fieldName]); 1933 } 1934 }); 1935 } 1936 1937 if (response.registration_exists) { 1938 showRegistrationExistsWarning(response); 1939 } 1940 1941 const globalError = document.getElementById('global-error'); 1942 const message = response.message || fallbackMessage; 1943 if (message && globalError) { 1944 globalError.textContent = message; 1945 globalError.style.display = 'block'; 1946 } 1947 } 1948 1949 // Handle network error 1950 function handleNetworkError(error) { 1951 const globalError = document.getElementById('global-error'); 1952 if (globalError) { 1953 globalError.textContent = error.message || 'Bir hata oluÅtu. Lütfen tekrar deneyin.'; 1954 globalError.style.display = 'block'; 1955 } 1956 console.error('AJAX submit hatası:', error); 1957 } 1958 1959 // Show upload media step 1960 function showUploadMediaStep(formType) { 1961 const validateStep = document.getElementById(`step-validate-info-${formType}`); 1962 const uploadStep = document.getElementById(`step-upload-media-${formType}`); 1963 1964 if (validateStep) validateStep.style.display = 'none'; 1965 if (uploadStep) uploadStep.style.display = 'block'; 1966 notifyAdminRegisterStep('upload_media'); 1967 } 1968 1969 function copyRegAddressToOtp(form) { 1970 if (!form) return; 1971 const pairs = [ 1972 ['otp_city_id', 'city_id'], 1973 ['otp_district_id', 'district_id'], 1974 ['otp_quarter_id', 'quarter_id'], 1975 ['otp_quarter_value', 'quarter_value'], 1976 ['otp_city_name', 'city_name'], 1977 ['otp_district_name', 'district_name'], 1978 ['otp_quarter_name', 'quarter_name'], 1979 ['otp_street_and_number', 'street_and_number'], 1980 ]; 1981 pairs.forEach(function (pair) { 1982 var t = document.getElementById(pair[0]); 1983 var s = form.querySelector('[name="' + pair[1] + '"]'); 1984 if (t && s) t.value = s.value || ''; 1985 }); 1986 } 1987 1988 // Show OTP modal - AJAX ile açıldıÄında form verilerini OTP formuna kopyala 1989 function showOTPModal(response) { 1990 const otpModal = document.getElementById('otpModal'); 1991 if (otpModal) { 1992 // Aktif formdan OTP hidden alanlarına veri kopyala (AJAX flow için kritik) 1993 const form = getActiveForm(); 1994 const formType = form ? (form.querySelector('[name="member_type"]') || {}).value || getActiveMemberType() : getActiveMemberType(); 1995 if (form) { 1996 const otpMemberType = document.getElementById('otp_member_type'); 1997 const otpFirstName = document.getElementById('otp_first_name'); 1998 const otpLastName = document.getElementById('otp_last_name'); 1999 const otpEmail = document.getElementById('otp_email'); 2000 const otpPhone = document.getElementById('otp_phone_number'); 2001 const otpPassword = document.getElementById('otp_password'); 2002 const otpPasswordConfirm = document.getElementById('otp_password_confirm'); 2003 const getVal = (name) => (form.querySelector('[name="' + name + '"]') || {}).value || ''; 2004 if (otpMemberType) otpMemberType.value = formType; 2005 if (otpFirstName) otpFirstName.value = getVal('first_name'); 2006 if (otpLastName) otpLastName.value = getVal('last_name'); 2007 if (otpEmail) otpEmail.value = getVal('email'); 2008 if (otpPhone) otpPhone.value = getVal('phone_number'); 2009 if (otpPassword) otpPassword.value = getVal('password'); 2010 if (otpPasswordConfirm) otpPasswordConfirm.value = getVal('password_confirm'); 2011 const otpReferralPhone = document.getElementById('otp_referral_phone'); 2012 if (otpReferralPhone) otpReferralPhone.value = getVal('referral_phone'); 2013 if (formType === 'corporate') { 2014 const otpCompanyName = document.getElementById('otp_company_name'); 2015 const otpCorporateType = document.getElementById('otp_corporate_type'); 2016 const otpCompanyLicenseNo = document.getElementById('otp_company_license_no'); 2017 const otpOfficeNo = document.getElementById('otp_office_no'); 2018 const otpSpkTcNo = document.getElementById('otp_spk_tc_no'); 2019 const corpType = getVal('corporate_type') || 'emlak'; 2020 if (otpCompanyName) otpCompanyName.value = getVal('company_name'); 2021 if (otpCorporateType) otpCorporateType.value = corpType; 2022 if (otpCompanyLicenseNo) otpCompanyLicenseNo.value = getVal('company_license_no'); 2023 if (otpOfficeNo) otpOfficeNo.value = getVal('office_no'); 2024 if (otpSpkTcNo) otpSpkTcNo.value = getVal('spk_tc_no'); 2025 if (corpType === 'spk') { 2026 const otpExpertiseCities = document.getElementById('otp_expertise_cities'); 2027 if (otpExpertiseCities) otpExpertiseCities.value = getVal('expertise_cities') || ''; 2028 const otpExpertise = document.getElementById('otp_expertise_quarters'); 2029 if (otpExpertise) otpExpertise.value = ''; 2030 } else { 2031 const otpExpertise = document.getElementById('otp_expertise_quarters'); 2032 if (otpExpertise) otpExpertise.value = getVal('expertise_quarters') || ''; 2033 const otpExpertiseCities = document.getElementById('otp_expertise_cities'); 2034 if (otpExpertiseCities) otpExpertiseCities.value = ''; 2035 } 2036 copyRegAddressToOtp(form); 2037 } else if (formType === 'consultant') { 2038 const otpConsultantType = document.getElementById('otp_consultant_type'); 2039 const otpConsultantLicense = document.getElementById('otp_consultant_license_no'); 2040 const otpCompanyProfileId = document.getElementById('otp_company_profile_id'); 2041 const consultantType = getVal('consultant_type') || 'emlak'; 2042 const isConsultantSpk = shouldConsultantUseSpkFlow(consultantType); 2043 if (otpConsultantType) otpConsultantType.value = consultantType; 2044 if (otpConsultantLicense) otpConsultantLicense.value = getVal('consultant_license_no') || ''; 2045 if (otpCompanyProfileId) otpCompanyProfileId.value = getVal('company_profile_id'); 2046 if (isConsultantSpk) { 2047 const otpExpertiseCities = document.getElementById('otp_expertise_cities'); 2048 if (otpExpertiseCities) otpExpertiseCities.value = getVal('expertise_cities') || ''; 2049 const otpExpertise = document.getElementById('otp_expertise_quarters'); 2050 if (otpExpertise) otpExpertise.value = ''; 2051 } else { 2052 const otpExpertise = document.getElementById('otp_expertise_quarters'); 2053 if (otpExpertise) otpExpertise.value = getVal('expertise_quarters') || ''; 2054 const otpExpertiseCities = document.getElementById('otp_expertise_cities'); 2055 if (otpExpertiseCities) otpExpertiseCities.value = ''; 2056 } 2057 copyRegAddressToOtp(form); 2058 } 2059 } 2060 otpModal.classList.add('active');
2061 const phoneDisplay = document.getElementById('otpPhoneDisplay'); 2062 if (phoneDisplay && response.phone_number) { 2063 const phone = response.phone_number; 2064 phoneDisplay.textContent = phone.slice(0, 3) + '****' + phone.slice(-2); 2065 } 2066 setTimeout(function() { 2067 const otpInputs = document.querySelectorAll('.otp-input'); 2068 if (otpInputs.length > 0) otpInputs[0].focus(); 2069 }, 100); 2070 if (typeof updateResendTimer === 'function') updateResendTimer(); 2071 } 2072 } 2073 2074 // Form submit handler 2075 async function handleFormSubmit(event, step, buttonId, formType) { 2076 event.preventDefault(); 2077 2078 syncMemberTypeInput(formType); 2079 const form = getFormByType(formType); 2080 if (!form) { 2081 handleNetworkError(new Error('Kayıt formu bulunamadı. Sayfayı yenileyip tekrar deneyin.')); 2082 return; 2083 } 2084 2085 if (formType === 'corporate' && step === 'validate_info') { 2086 const corporateType = (document.getElementById('corporate_type') || {}).value || 'emlak'; 2087 if (corporateType === 'lihkab') { 2088 const officeNoError = document.getElementById('error-office_no_corporate'); 2089 if (officeNoError) { 2090 officeNoError.style.display = 'none'; 2091 officeNoError.textContent = ''; 2092 } 2093 } 2094 } 2095 2096 // DanıÅman: SPK seçiliyse Lisans No zorunlu (admin hariç) 2097 if (formType === 'consultant' && step === 'validate_info' && !adminMode) { 2098 const consultantType = (document.getElementById('consultant_type') || {}).value || 'emlak'; 2099 if (consultantType === 'spk') { 2100 const licenseInput = document.getElementById('consultant_license_no'); 2101 const licenseVal = (licenseInput && licenseInput.value) ? licenseInput.value.trim() : ''; 2102 if (!licenseVal) { 2103 const errEl = document.getElementById('error-consultant_license_no_consultant'); 2104 if (errEl) { 2105 errEl.textContent = 'SPK Lisanslı DeÄerleme Uzmanı için Lisans No gereklidir.'; 2106 errEl.style.display = 'block'; 2107 } 2108 if (consultantLicenseWrapper) consultantLicenseWrapper.scrollIntoView({ behavior: 'smooth' }); 2109 return; 2110 } 2111 } 2112 } 2113 // DanıÅman: firma seçimi zorunlu (admin hariç) 2114 if (formType === 'consultant' && step === 'validate_info' && !adminMode) { 2115 const profileInput = document.getElementById('company_profile_id'); 2116 const profileVal = (profileInput && profileInput.value) ? profileInput.value.trim() : ''; 2117 if (!profileVal) { 2118 const errEl = document.getElementById('error-company_profile_id_consultant'); 2119 if (errEl) { 2120 errEl.textContent = 'DanıÅman üyelik için firma seçimi zorunludur.'; 2121 errEl.style.display = 'block'; 2122 } 2123 const companySelect = document.getElementById('company_profile_select'); 2124 if (companySelect) companySelect.classList.add('error'); 2125 return; 2126 } 2127 const consultantType = (document.getElementById('consultant_type') || {}).value || 'emlak'; 2128 const isConsultantSpk = shouldConsultantUseSpkFlow(consultantType); 2129 if (isConsultantSpk) { 2130 const eduLevel = document.getElementById('education_level_consultant'); 2131 const eduVal = (eduLevel && eduLevel.value) ? parseInt(eduLevel.value, 10) : null; 2132 if (eduVal !== 1 && eduVal !== 2) { 2133 const errEl = document.getElementById('error-education_level_consultant'); 2134 if (errEl) { 2135 errEl.textContent = 'SPK Lisanslı firmaya baÄlı danıÅmanlar için eÄitim seviyesi (Lisans veya Ãn Lisans) seçiniz.'; 2136 errEl.style.display = 'block'; 2137 } 2138 document.getElementById('graduation-section-consultant')?.scrollIntoView({ behavior: 'smooth' }); 2139 return; 2140 } 2141 const univId = document.getElementById('university_id_consultant'); 2142 if ((!univId || !univId.value) && (eduVal === 1 || eduVal === 2)) { 2143 const errEl = document.getElementById('error-education_level_consultant'); 2144 if (errEl) { 2145 errEl.textContent = 'Ãniversite seçiniz.'; 2146 errEl.style.display = 'block'; 2147 } 2148 document.getElementById('graduation-section-consultant')?.scrollIntoView({ behavior: 'smooth' }); 2149 return; 2150 } 2151 } 2152 } 2153 2154 // HTML5 validation check 2155 if (adminMode) { 2156 if (!adminValidateEmailOnly(form, formType)) { 2157 return; 2158 } 2159 } else if (!form.checkValidity()) { 2160 form.reportValidity(); 2161 return; 2162 } 2163 2164 // Loading state 2165 showLoading(buttonId); 2166 clearFieldErrors(formType); 2167 2168 // Hide global error 2169 const globalError = document.getElementById('global-error'); 2170 if (globalError) { 2171 globalError.style.display = 'none'; 2172 } 2173 2174 try { 2175 const response = await submitFormAjax(form, step); 2176 2177 if (response.success) { 2178 handleSuccess(response, step, formType); 2179 } else { 2180 handleErrors(response, formType); 2181 } 2182 } catch (error) { 2183 handleNetworkError(error); 2184 } finally { 2185 hideLoading(buttonId); 2186 } 2187 } 2188 2189 // ========== Tab Switching ========== 2190 const tabs = document.querySelectorAll('.tab'); 2191 const memberTypeInput = document.getElementById('member_type'); 2192 const formIndividual = document.getElementById('form-individual'); 2193 const formConsultant = document.getElementById('form-consultant'); 2194 const formCorporate = document.getElementById('form-corporate'); 2195 2196 function syncMemberTypeForms(activeType) { 2197 const mt = activeType || (memberTypeInput && memberTypeInput.value) || 'individual'; 2198 if (memberTypeInput) memberTypeInput.value = mt;
2199 tabs.forEach(t => t.classList.toggle('active', t.dataset.tab === mt)); 2200 if (formIndividual) formIndividual.style.display = mt === 'individual' ? 'block' : 'none'; 2201 if (formConsultant) formConsultant.style.display = mt === 'consultant' ? 'block' : 'none'; 2202 if (formCorporate) formCorporate.style.display = mt === 'corporate' ? 'block' : 'none'; 2203 // window.* yalnızca baÄımlı const'lar hazır olduktan sonra atanır (TDZ koruması) 2204 if (mt === 'corporate' && typeof window.updateCorporateType === 'function') { 2205 const ct = document.getElementById('corporate_type'); 2206 window.updateCorporateType(ct ? ct.value || 'emlak' : 'emlak'); 2207 } 2208 if (mt === 'consultant' && typeof window.updateConsultantType === 'function') { 2209 const ct = document.getElementById('consultant_type'); 2210 window.updateConsultantType(ct ? ct.value || 'emlak' : 'emlak'); 2211 } 2212 } 2213 2214 const REGISTER_TYPE_LABELS = { 2215 corporate: 'Kurumsal', 2216 consultant: 'DanıÅman', 2217 individual: 'Bireysel', 2218 }; 2219 const registerTypeStep = document.getElementById('register-type-step'); 2220 const registerFormArea = document.getElementById('register-form-area'); 2221 const registerSelectedTypeBar = document.getElementById('register-selected-type-bar'); 2222 const registerSelectedTypeLabel = document.getElementById('register-selected-type-label'); 2223 const registerChangeTypeBtn = document.getElementById('register-change-type-btn'); 2224 2225 function showRegisterTypeStep() { 2226 if (!registerTypeStep || adminMode) return; 2227 registerTypeStep.style.display = 'block'; 2228 if (registerFormArea) registerFormArea.style.display = 'none'; 2229 if (registerSelectedTypeBar) registerSelectedTypeBar.style.display = 'none'; 2230 } 2231 2232 function showRegisterFormStep(activeType) { 2233 syncMemberTypeForms(activeType); 2234 if (adminMode) return; 2235 if (registerTypeStep) registerTypeStep.style.display = 'none'; 2236 if (registerFormArea) registerFormArea.style.display = 'block'; 2237 if (registerSelectedTypeBar) registerSelectedTypeBar.style.display = 'flex'; 2238 if (registerSelectedTypeLabel) { 2239 registerSelectedTypeLabel.textContent = REGISTER_TYPE_LABELS[activeType] || activeType; 2240 } 2241 const sc = document.querySelector('.pp-auth-portal__forms-scroll > .pp-auth-panel'); 2242 if (sc) sc.scrollTop = 0; 2243 } 2244 2245 function initRegisterMemberTypeFlow() { 2246 if (adminMode) { 2247 syncMemberTypeForms();
2248 tabs.forEach(tab => { 2249 tab.addEventListener('click', function() { 2250 syncMemberTypeForms(this.dataset.tab); 2251 }); 2252 }); 2253 return; 2254 } 2255 2256 document.querySelectorAll('.register-type-card[data-member-type]').forEach(function(card) { 2257 card.addEventListener('click', function() { 2258 showRegisterFormStep(card.getAttribute('data-member-type')); 2259 }); 2260 }); 2261 2262 if (registerChangeTypeBtn) { 2263 registerChangeTypeBtn.addEventListener('click', function(e) { 2264 e.preventDefault(); 2265 showRegisterTypeStep(); 2266 }); 2267 } 2268 2269 let urlMemberType = null; 2270 try { 2271 urlMemberType = new URL(window.location.href).searchParams.get('member_type'); 2272 } catch (err) { /* ignore */ } 2273 2274 if (urlMemberType && ['individual', 'consultant', 'corporate'].indexOf(urlMemberType) !== -1) { 2275 showRegisterFormStep(urlMemberType); 2276 } else { 2277 showRegisterTypeStep(); 2278 if (formIndividual) formIndividual.style.display = 'none'; 2279 if (formConsultant) formConsultant.style.display = 'none'; 2280 if (formCorporate) formCorporate.style.display = 'none'; 2281 } 2282 } 2283 2284 // initRegisterMemberTypeFlow: corporateTypeInput / updateCorporateType 2285 // tanımlandıktan sonra çaÄrılmalı (TDZ). Sonunda tetiklenir. 2286 2287 // ========== Form Submit Handlers ========== 2288 2289 // Bireysel form submit buttons 2290 const submitBtnIndividual = document.getElementById('submit-btn-individual'); 2291 if (submitBtnIndividual) { 2292 submitBtnIndividual.addEventListener('click', function(e) { 2293 handleFormSubmit(e, 'validate_info', 'submit-btn-individual', 'individual'); 2294 }); 2295 } 2296 2297 const continueMediaBtnIndividual = document.getElementById('continue-media-btn-individual'); 2298 if (continueMediaBtnIndividual) { 2299 continueMediaBtnIndividual.addEventListener('click', function(e) { 2300 handleFormSubmit(e, 'upload_media', 'continue-media-btn-individual', 'individual'); 2301 }); 2302 } 2303 2304 const skipMediaBtnIndividual = document.getElementById('skip-media-btn-individual'); 2305 if (skipMediaBtnIndividual) { 2306 skipMediaBtnIndividual.addEventListener('click', function(e) { 2307 handleFormSubmit(e, 'send_otp', 'skip-media-btn-individual', 'individual'); 2308 }); 2309 } 2310 2311 // DanıÅman form submit buttons 2312 const submitBtnConsultant = document.getElementById('submit-btn-consultant'); 2313 if (submitBtnConsultant) { 2314 submitBtnConsultant.addEventListener('click', function(e) { 2315 handleFormSubmit(e, 'validate_info', 'submit-btn-consultant', 'consultant'); 2316 }); 2317 } 2318 2319 // DanıÅman: Media upload -> Uzmanlık Bölgeleri adımına git (OTP'ye deÄil) 2320 const continueMediaBtnConsultant = document.getElementById('continue-media-btn-consultant'); 2321 if (continueMediaBtnConsultant) { 2322 continueMediaBtnConsultant.addEventListener('click', async function(e) { 2323 e.preventDefault(); 2324 if (shouldSkipExpertiseStep('consultant')) { 2325 finalizeRegistrationFromMediaStep(e, 'consultant', 'continue-media-btn-consultant'); 2326 return; 2327 } 2328 const uploadStep = document.getElementById('step-upload-media-consultant'); 2329 const expertiseStep = document.getElementById('step-expertise-areas-consultant'); 2330 if (uploadStep) uploadStep.style.display = 'none'; 2331 if (expertiseStep) expertiseStep.style.display = 'block'; 2332 if (typeof showExpertiseAreasStep === 'function') await showExpertiseAreasStep('consultant'); 2333 }); 2334 } 2335 2336 const skipMediaBtnConsultant = document.getElementById('skip-media-btn-consultant'); 2337 if (skipMediaBtnConsultant) { 2338 skipMediaBtnConsultant.addEventListener('click', async function(e) { 2339 e.preventDefault(); 2340 if (shouldSkipExpertiseStep('consultant')) { 2341 finalizeRegistrationFromMediaStep(e, 'consultant', 'skip-media-btn-consultant'); 2342 return; 2343 } 2344 const uploadStep = document.getElementById('step-upload-media-consultant'); 2345 const expertiseStep = document.getElementById('step-expertise-areas-consultant'); 2346 if (uploadStep) uploadStep.style.display = 'none'; 2347 if (expertiseStep) expertiseStep.style.display = 'block'; 2348 if (typeof showExpertiseAreasStep === 'function') await showExpertiseAreasStep('consultant'); 2349 }); 2350 } 2351 2352 // Kurumsal form submit buttons 2353 const submitBtnCorporate = document.getElementById('submit-btn-corporate'); 2354 if (submitBtnCorporate) { 2355 submitBtnCorporate.addEventListener('click', function(e) { 2356 handleFormSubmit(e, 'validate_info', 'submit-btn-corporate', 'corporate'); 2357 }); 2358 } 2359 2360 // Kurumsal: Media upload ->
2360 Uzmanlık Bölgeleri adımına git (OTP'ye deÄil) 2361 const continueMediaBtnCorporate = document.getElementById('continue-media-btn-corporate'); 2362 if (continueMediaBtnCorporate) { 2363 continueMediaBtnCorporate.addEventListener('click', function(e) { 2364 e.preventDefault(); 2365 if (shouldSkipExpertiseStep('corporate')) { 2366 finalizeRegistrationFromMediaStep(e, 'corporate', 'continue-media-btn-corporate'); 2367 return; 2368 } 2369 const uploadStep = document.getElementById('step-upload-media-corporate'); 2370 const expertiseStep = document.getElementById('step-expertise-areas-corporate'); 2371 if (uploadStep) uploadStep.style.display = 'none'; 2372 if (expertiseStep) expertiseStep.style.display = 'block'; 2373 if (typeof initExpertiseAreas === 'function') initExpertiseAreas('corporate'); 2374 }); 2375 } 2376 2377 const skipMediaBtnCorporate = document.getElementById('skip-media-btn-corporate'); 2378 if (skipMediaBtnCorporate) { 2379 skipMediaBtnCorporate.addEventListener('click', function(e) { 2380 e.preventDefault(); 2381 if (shouldSkipExpertiseStep('corporate')) { 2382 finalizeRegistrationFromMediaStep(e, 'corporate', 'skip-media-btn-corporate'); 2383 return; 2384 } 2385 const uploadStep = document.getElementById('step-upload-media-corporate'); 2386 const expertiseStep = document.getElementById('step-expertise-areas-corporate'); 2387 if (uploadStep) uploadStep.style.display = 'none'; 2388 if (expertiseStep) expertiseStep.style.display = 'block'; 2389 if (typeof initExpertiseAreas === 'function') initExpertiseAreas('corporate'); 2390 }); 2391 } 2392 2393 // ========== Input Formatting ========== 2394 2395 // Phone number formatting - Bireysel 2396 const phoneInputIndividual = document.getElementById('phone_number_individual'); 2397 if (phoneInputIndividual) { 2398 phoneInputIndividual.addEventListener('input', function(e) { 2399 this.value = this.value.replace(/\D/g, '').slice(0, 10); 2400 }); 2401 } 2402 2403 // Phone number formatting - Kurumsal 2404 const phoneInputCorporate = document.getElementById('phone_number_corporate'); 2405 if (phoneInputCorporate) { 2406 phoneInputCorporate.addEventListener('input', function(e) { 2407 this.value = this.value.replace(/\D/g, '').slice(0, 10); 2408 }); 2409 } 2410 2411 // Phone number formatting - DanıÅman 2412 const phoneInputConsultant = document.getElementById('phone_number_consultant'); 2413 if (phoneInputConsultant) { 2414 phoneInputConsultant.addEventListener('input', function(e) { 2415 this.value = this.value.replace(/\D/g, '').slice(0, 10); 2416 }); 2417 } 2418 2419 // Referans telefon: format + blur lookup (isim/soyisim) 2420 (function bindReferralPhoneLookup() { 2421 const inputs = document.querySelectorAll('.referral-phone-input'); 2422 if (!inputs.length) return; 2423 2424 async function loadReferralHintAmount() { 2425 try { 2426 const res = await fetch('/api/gifts/', { 2427 method: 'GET', 2428 credentials: 'same-origin', 2429 headers: { 'X-Requested-With': 'XMLHttpRequest' }, 2430 }); 2431 const data = await res.json(); 2432 const items = (data && data.engagement) || []; 2433 const rule = items.find(function (item) { 2434 return item && item.event_type === 'referral_phone_referred_bonus'; 2435 }); 2436 const credits = rule && Number(rule.credits) > 0 ? Number(rule.credits) : 5; 2437 document.querySelectorAll('.referral-phone-bonus-amount').forEach(function (el) { 2438 el.textContent = String(credits); 2439 }); 2440 } catch (err) { 2441 // seed fallback 5 zaten HTML'de 2442 } 2443 } 2444 loadReferralHintAmount(); 2445 2446 async function lookupReferral(input) { 2447 const previewId = input.getAttribute('data-referral-preview'); 2448 const preview = previewId ? document.getElementById(previewId) : null; 2449 const digits = (input.value || '').replace(/\D/g, '').slice(0, 10); 2450 input.value = digits; 2451 if (!preview) return; 2452 if (digits.length !== 10) { 2453 preview.textContent = ''; 2454 return; 2455 } 2456 preview.textContent = 'Kontrol ediliyorâ¦'; 2457 try { 2458 const res = await fetch('/api/auth/referral-phone/lookup/?phone=' + encodeURIComponent(digits), { 2459 method: 'GET', 2460 credentials: 'same-origin', 2461 headers: { 'X-Requested-With': 'XMLHttpRequest' }, 2462 }); 2463 const data = await res.json(); 2464 if (data && data.exists) { 2465 const name = ((data.first_name || '') + ' ' + (data.last_name || '')).trim(); 2466 preview.textContent = name || 'Ãye bulundu'; 2467 } else { 2468 preview.textContent = ''; 2469 } 2470 } catch (err) { 2471 preview.textContent = ''; 2472 } 2473 } 2474
2475 inputs.forEach(function (input) { 2476 input.addEventListener('input', function () { 2477 this.value = this.value.replace(/\D/g, '').slice(0, 10); 2478 const previewId = this.getAttribute('data-referral-preview'); 2479 const preview = previewId ? document.getElementById(previewId) : null; 2480 if (preview && this.value.length !== 10) preview.textContent = ''; 2481 }); 2482 input.addEventListener('blur', function () { 2483 lookupReferral(this); 2484 }); 2485 }); 2486 })(); 2487 2488 // ========== Kurumsal Firma Tipi Seçimi ========== 2489 const corporateTypeInput = document.getElementById('corporate_type'); 2490 const corporateTypeEmlak = document.getElementById('corporate_type_emlak'); 2491 const corporateTypeSpk = document.getElementById('corporate_type_spk'); 2492 const corporateTypeLihkab = document.getElementById('corporate_type_lihkab'); 2493 const spkTcWrapper = document.getElementById('spk_tc_wrapper'); 2494 const spkTcInput = document.getElementById('spk_tc_no'); 2495 const officeNoWrapper = document.getElementById('office_no_wrapper'); 2496 const officeNoInput = document.getElementById('office_no_corporate'); 2497 const companyNameInput = document.getElementById('company_name'); 2498 const companyLicenseInput = document.getElementById('company_license_no'); 2499 const graduationSectionCorporate = document.getElementById('graduation-section-corporate'); 2500 2501 function updateCorporateType(type) { 2502 if (!corporateTypeInput) return; 2503 const isSpk = type === 'spk'; 2504 const isLihkab = type === 'lihkab'; 2505 corporateTypeInput.value = type; 2506 if (corporateTypeEmlak) { 2507 corporateTypeEmlak.classList.toggle('active', type === 'emlak'); 2508 } 2509 if (corporateTypeSpk) { 2510 corporateTypeSpk.classList.toggle('active', isSpk); 2511 } 2512 if (corporateTypeLihkab) { 2513 corporateTypeLihkab.classList.toggle('active', isLihkab); 2514 } 2515 if (spkTcWrapper) spkTcWrapper.style.display = isSpk ? 'block' : 'none'; 2516 if (spkTcInput) spkTcInput.required = isSpk && !adminMode; 2517 if (officeNoWrapper) officeNoWrapper.style.display = isLihkab ? 'block' : 'none'; 2518 if (officeNoInput) officeNoInput.required = false; 2519 if (companyNameInput) { 2520 companyNameInput.placeholder = adminMode 2521 ? (isLihkab ? 'Büro Adı' : 'Firma Marka/Ãnvan') 2522 : (isLihkab ? 'Büro Adı (opsiyonel)' : 'Firma Marka/Ãnvan (opsiyonel)'); 2523 companyNameInput.required = false; 2524 } 2525 if (companyLicenseInput) { 2526 companyLicenseInput.placeholder = isLihkab ? 'Lisans No (opsiyonel)' : '7 haneli yetki belge no (opsiyonel)'; 2527 } 2528 if (graduationSectionCorporate) { 2529 graduationSectionCorporate.style.display = adminMode ? 'none' : (isLihkab ? 'none' : 'block'); 2530 } 2531 // SPK seçiliyse mezuniyet zorunlu 2532 const gradBadge = document.getElementById('graduation-required-badge-corporate'); 2533 const gradNote = document.getElementById('graduation-note-text-corporate'); 2534 if (gradBadge) gradBadge.style.display = isSpk ? 'inline' : 'none'; 2535 if (gradNote) gradNote.textContent = isSpk 2536 ? 'SPK Lisanslı DeÄerleme Firması için üniversite bilgileri zorunludur.' 2537 : 'Mezuniyetiniz uygulama üzerinde uzmanlık puanınızı arttırır ve uygulamanın bir çok alanda size öncelik vermesini saÄlar.'; 2538 2539 // SPK seçiliyse: OrtaöÄretim ve Ãn Lisans tıklanamaz, Lisans seçili 2540 const edu0 = document.querySelector('#form-corporate input[name="education_level_radio_corporate"][value="0"]'); 2541 const edu2 = document.querySelector('#form-corporate input[name="education_level_radio_corporate"][value="2"]'); 2542 const edu1 = document.querySelector('#form-corporate input[name="education_level_radio_corporate"][value="1"]'); 2543 const eduLevelHidden = document.getElementById('education_level_corporate'); 2544 const higherFields = document.getElementById('higher-education-fields-corporate'); 2545 const skipCheckbox = document.getElementById('skip_diploma_checkbox_corporate'); 2546 const eduLabels = document.querySelectorAll('#form-corporate .education-level-option'); 2547 2548 if (isSpk) { 2549 if (edu0) { edu0.disabled = true; edu0.checked = false; } 2550 if (edu2) { edu2.disabled = true; edu2.checked = false; } 2551 if (edu1) { edu1.disabled = false; edu1.checked = true; edu1.dispatchEvent(new Event('change')); } 2552 if (eduLevelHidden) eduLevelHidden.value = '1'; 2553 if (higherFields) higherFields.classList.add('visible'); 2554 if (skipCheckbox) skipCheckbox.disabled = false;
2555 eduLabels.forEach(function(lbl) { 2556 const lvl = parseInt(lbl.dataset.level, 10); 2557 lbl.classList.toggle('selected', lvl === 1); 2558 lbl.style.pointerEvents = (lvl === 0 || lvl === 2) ? 'none' : ''; 2559 lbl.style.opacity = (lvl === 0 || lvl === 2) ? '0.5' : ''; 2560 }); 2561 } else { 2562 if (edu0) edu0.disabled = false; 2563 if (edu2) edu2.disabled = false; 2564 if (edu1) edu1.disabled = false; 2565 if (skipCheckbox) skipCheckbox.disabled = false; 2566 eduLabels.forEach(function(lbl) { 2567 lbl.style.pointerEvents = ''; 2568 lbl.style.opacity = ''; 2569 }); 2570 if (isLihkab) { 2571 if (edu0) edu0.checked = false; 2572 if (edu2) edu2.checked = false; 2573 if (edu1) edu1.checked = false; 2574 if (eduLevelHidden) eduLevelHidden.value = ''; 2575 if (higherFields) higherFields.classList.remove('visible'); 2576 const universityHidden = document.getElementById('university_id_corporate'); 2577 const departmentHidden = document.getElementById('department_id_corporate'); 2578 const customDepartmentHidden = document.getElementById('custom_department_corporate'); 2579 const universitySelect = document.getElementById('university_select_corporate'); 2580 const departmentSelect = document.getElementById('department_select_corporate'); 2581 const customDepartmentInput = document.getElementById('custom_department_input_corporate'); 2582 if (universityHidden) universityHidden.value = ''; 2583 if (departmentHidden) departmentHidden.value = ''; 2584 if (customDepartmentHidden) customDepartmentHidden.value = ''; 2585 if (universitySelect) universitySelect.value = ''; 2586 if (departmentSelect) departmentSelect.value = ''; 2587 if (customDepartmentInput) customDepartmentInput.value = ''; 2588 } 2589 } 2590 } 2591 2592 if (corporateTypeEmlak) { 2593 corporateTypeEmlak.addEventListener('click', function() { 2594 updateCorporateType('emlak'); 2595 }); 2596 } 2597 if (corporateTypeSpk) { 2598 corporateTypeSpk.addEventListener('click', function() { 2599 updateCorporateType('spk'); 2600 }); 2601 } 2602 if (corporateTypeLihkab) { 2603 corporateTypeLihkab.addEventListener('click', function() { 2604 updateCorporateType('lihkab'); 2605 }); 2606 } 2607 // İlk yüklemede varsayılan ve tab deÄiÅiminde kullanım için global 2608 window.updateCorporateType = updateCorporateType; 2609 const initialType = corporateTypeInput ? corporateTypeInput.value || 'emlak' : 'emlak'; 2610 updateCorporateType(initialType); 2611 2612 // SPK TC sadece rakam 2613 if (spkTcInput) { 2614 spkTcInput.addEventListener('input', function() { 2615 this.value = this.value.replace(/\D/g, '').slice(0, 11); 2616 }); 2617 } 2618 2619 // DanıÅman: firma seçimi (company_profile_id) 2620 let selectedCompanyProfile = { id: null, corporate_type: null, is_expert: false }; 2621 2622 function applySelectedCompanyProfile(data) { 2623 selectedCompanyProfile = data || { id: null, corporate_type: null, is_expert: false }; 2624 const hidden = document.getElementById('company_profile_id'); 2625 const consultantTypeInput = document.getElementById('consultant_type'); 2626 if (hidden) hidden.value = selectedCompanyProfile.id ? String(selectedCompanyProfile.id) : ''; 2627 if (consultantTypeInput) { 2628 consultantTypeInput.value = selectedCompanyProfile.corporate_type || 'emlak'; 2629 } 2630 if (typeof updateConsultantType === 'function') { 2631 updateConsultantType(selectedCompanyProfile.corporate_type || 'emlak'); 2632 } 2633 const errEl = document.getElementById('error-company_profile_id_consultant'); 2634 if (errEl) { 2635 errEl.style.display = 'none'; 2636 errEl.textContent = ''; 2637 } 2638 const companySelect = document.getElementById('company_profile_select'); 2639 if (companySelect) companySelect.classList.remove('error'); 2640 } 2641 2642 function initCompanyProfileSelect() { 2643 const select = document.getElementById('company_profile_select'); 2644 if (!select || !isSelect2Ready() || select.dataset.initialized === 'true') return; 2645 select.dataset.initialized = 'true'; 2646 const $select = window.jQuery(select); 2647 $select.select2({ 2648 placeholder: 'Firma ara (ad veya profil no)', 2649 allowClear: true, 2650 minimumInputLength: 0, 2651 width: '100%', 2652 ajax: { 2653 url: '/api/auth/company/list/', 2654 dataType: 'json', 2655 delay: 300, 2656 data: function(params) { 2657 return { q: params.term || '', limit: 20 }; 2658 }, 2659 processResults: function(data) {
2660 const companies = (data && data.data && data.data.companies) ? data.data.companies : []; 2661 return { 2662 results: companies.map(function(c) { 2663 const label = (c.company_name || 'Firma') + ' (#' + c.company_profile_id + ')'; 2664 return { 2665 id: c.company_profile_id, 2666 text: label, 2667 corporate_type: c.corporate_type || 'emlak', 2668 is_expert: !!c.is_expert, 2669 }; 2670 }), 2671 }; 2672 }, 2673 cache: true, 2674 }, 2675 dropdownCssClass: 'pp-auth-select2-dropdown', 2676 selectionCssClass: 'pp-auth-select2-selection', 2677 }); 2678 $select.on('select2:select', function(e) { 2679 const item = e.params.data || {}; 2680 applySelectedCompanyProfile({ 2681 id: item.id, 2682 corporate_type: item.corporate_type || 'emlak', 2683 is_expert: !!item.is_expert, 2684 }); 2685 }); 2686 $select.on('select2:clear', function() { 2687 applySelectedCompanyProfile(null); 2688 }); 2689 const initialId = (document.getElementById('company_profile_id') || {}).value; 2690 if (initialId) { 2691 selectedCompanyProfile.id = initialId; 2692 } 2693 } 2694 initCompanyProfileSelect(); 2695 2696 function updateConsultantGraduationRequired(isExpert) { 2697 const badge = document.getElementById('graduation-required-badge-consultant'); 2698 const noteText = document.getElementById('graduation-note-text-consultant'); 2699 const edu0 = document.querySelector('#form-consultant input[name="education_level_radio_consultant"][value="0"]'); 2700 const edu2 = document.querySelector('#form-consultant input[name="education_level_radio_consultant"][value="2"]'); 2701 const edu1 = document.querySelector('#form-consultant input[name="education_level_radio_consultant"][value="1"]'); 2702 const eduLevelHidden = document.getElementById('education_level_consultant'); 2703 const skipCheckbox = document.getElementById('skip_diploma_checkbox_consultant'); 2704 const errEl = document.getElementById('error-education_level_consultant'); 2705 if (badge) badge.style.display = isExpert ? 'inline' : 'none'; 2706 if (noteText) noteText.textContent = isExpert 2707 ? 'SPK Lisanslı DeÄerleme Firmasına baÄlı danıÅmanlar için üniversite bilgileri zorunludur.' 2708 : 'Mezuniyetiniz uygulama üzerinde uzmanlık puanınızı arttırır ve uygulamanın bir çok alanda size öncelik vermesini saÄlar.'; 2709 if (errEl) errEl.style.display = 'none'; 2710 if (isExpert) { 2711 if (edu0) { edu0.closest('label').style.opacity = '0.5'; edu0.disabled = true; } 2712 if (edu2) { edu2.closest('label').style.opacity = ''; edu2.disabled = false; } 2713 if (edu1) { edu1.closest('label').style.opacity = ''; edu1.disabled = false; } 2714 if (!eduLevelHidden || !eduLevelHidden.value || eduLevelHidden.value === '0') { 2715 if (edu1) { 2716 edu1.checked = true; 2717 if (eduLevelHidden) eduLevelHidden.value = '1'; 2718 const higherFields = document.getElementById('higher-education-fields-consultant'); 2719 if (higherFields) higherFields.classList.add('visible'); 2720 if (typeof loadUniversities === 'function' && typeof populateSelect === 'function') { 2721 const univSelect = document.getElementById('university_select_consultant'); 2722 if (univSelect) { 2723 loadUniversities().then(universities => { 2724 populateSelect(univSelect, universities, 'id', 'name', 'Ãniversite Seçiniz *'); 2725 }); 2726 loadDepartments(1).then(depts => { 2727 const deptSelect = document.getElementById('department_select_consultant'); 2728 if (deptSelect) populateSelect(deptSelect, depts, 'id', 'name', 'Bölüm SeÃ
2728§iniz'); 2729 }); 2730 } 2731 } 2732 } 2733 } 2734 } else { 2735 if (edu0) { edu0.closest('label').style.opacity = ''; edu0.disabled = false; } 2736 if (edu2) edu2.disabled = false; 2737 if (edu1) edu1.disabled = false; 2738 if (skipCheckbox) skipCheckbox.disabled = false; 2739 } 2740 } 2741 2742 // ========== Password Validation ========== 2743 2744 function hasRegistrationUppercase(pwd) { 2745 return Array.from(pwd || '').some(function (ch) { 2746 return ch !== ch.toLocaleLowerCase('tr-TR'); 2747 }); 2748 } 2749 2750 function updatePasswordRules(formType, pwd) { 2751 const rulesEl = document.getElementById('password-rules-' + formType); 2752 if (!rulesEl) return; 2753 const states = { 2754 minLength: (pwd || '').length >= 8, 2755 uppercase: hasRegistrationUppercase(pwd || ''), 2756 }; 2757 rulesEl.querySelectorAll('.password-rule').forEach(function (li) { 2758 const ok = !!states[li.getAttribute('data-rule')]; 2759 li.classList.toggle('is-ok', ok); 2760 li.classList.toggle('is-fail', !ok); 2761 const mark = li.querySelector('.password-rule__mark'); 2762 if (mark) mark.textContent = ok ? 'â' : 'â'; 2763 }); 2764 } 2765 2766 function setupPasswordValidation(formType) { 2767 const password = document.getElementById(`password_${formType}`); 2768 const passwordConfirm = document.getElementById(`password_confirm_${formType}`); 2769 const passwordError = document.getElementById(`password-error-${formType}`); 2770 const passwordMatchError = document.getElementById(`password-match-error-${formType}`); 2771 2772 if (!password || !passwordConfirm) return; 2773 2774 updatePasswordRules(formType, password.value || ''); 2775 2776 function validatePassword() { 2777 const pwd = password.value; 2778 const pwdConfirm = passwordConfirm.value; 2779 let hasError = false; 2780 2781 updatePasswordRules(formType, pwd); 2782 2783 if (pwd) { 2784 if (pwd.length < 8) { 2785 if (passwordError) { 2786 passwordError.textContent = 'Åifre en az 8 karakter olmalıdır'; 2787 passwordError.style.display = 'block'; 2788 } 2789 password.classList.add('error'); 2790 hasError = true; 2791 } else if (!hasRegistrationUppercase(pwd)) { 2792 if (passwordError) { 2793 passwordError.textContent = 'Åifre en az bir büyük harf içermelidir'; 2794 passwordError.style.display = 'block'; 2795 } 2796 password.classList.add('error'); 2797 hasError = true; 2798 } else { 2799 if (passwordError) passwordError.style.display = 'none'; 2800 password.classList.remove('error'); 2801 } 2802 } else { 2803 if (passwordError) passwordError.style.display = 'none'; 2804 password.classList.remove('error'); 2805 } 2806 2807 if (pwdConfirm) { 2808 if (pwd && pwdConfirm && pwd !== pwdConfirm) { 2809 if (passwordMatchError) { 2810 passwordMatchError.textContent = 'Åifreler eÅleÅmiyor'; 2811 passwordMatchError.style.display = 'block'; 2812 } 2813 passwordConfirm.classList.add('error'); 2814 hasError = true; 2815 } else { 2816 if (passwordMatchError) passwordMatchError.style.display = 'none'; 2817 passwordConfirm.classList.remove('error'); 2818 } 2819 } 2820 2821 return !hasError; 2822 } 2823 2824 password.addEventListener('input', validatePassword); 2825 password.addEventListener('blur', validatePassword); 2826 passwordConfirm.addEventListener('input', validatePassword); 2827 passwordConfirm.addEventListener('blur', validatePassword); 2828 } 2829 2830 setupPasswordValidation('individual'); 2831 setupPasswordValidation('consultant'); 2832 setupPasswordValidation('corporate'); 2833 2834 // ========== Avatar/Logo Preview ========== 2835 2836 function setupFilePreview(inputId, previewId, initialId, isLogo = false) { 2837 const input = document.getElementById(inputId); 2838 if (!input) return; 2839 2840 input.addEventListener('change', function(e) { 2841 const file = e.target.files[0]; 2842 if (file) { 2843 const maxSize = 5 * 1024 * 1024; 2844 const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']; 2845 2846 if (file.size > maxSize) { 2847 alert('Dosya boyutu 5MB\'dan küçük olmalıdır.'); 2848 this.value = ''; 2849 return; 2850 } 2851 2852 if (!allowedTypes.includes(file.type)) { 2853 alert('Sadece JPEG, PNG, GIF ve WebP formatları de
2853steklenir.'); 2854 this.value = ''; 2855 return; 2856 } 2857 2858 const reader = new FileReader(); 2859 reader.onload = function(e) { 2860 const preview = document.getElementById(previewId); 2861 const initial = document.getElementById(initialId); 2862 2863 if (preview) { 2864 preview.src = e.target.result; 2865 preview.style.display = 'block'; 2866 } 2867 if (initial) { 2868 initial.style.display = 'none'; 2869 } 2870 }; 2871 reader.readAsDataURL(file); 2872 } 2873 }); 2874 } 2875 2876 // Avatar previews 2877 setupFilePreview('avatarInputIndividual', 'avatarPreviewIndividual', 'avatarInitialIndividual'); 2878 setupFilePreview('avatarInputConsultant', 'avatarPreviewConsultant', 'avatarInitialConsultant'); 2879 setupFilePreview('avatarInputCorporate', 'avatarPreviewCorporate', 'avatarInitialCorporate'); 2880 2881 // Logo preview 2882 setupFilePreview('logoInputCorporate', 'logoPreviewImgCorporate', 'logoPlaceholderCorporate', true); 2883 2884 // OTP Input handling (6 separate inputs) 2885 const otpInputs = document.querySelectorAll('.otp-input'); 2886 const otpValueInput = document.getElementById('otpValue'); 2887 2888 otpInputs.forEach((input, index) => { 2889 input.addEventListener('input', function(e) { 2890 const value = this.value.replace(/\D/g, ''); 2891 this.value = value.slice(0, 1); 2892 2893 if (value && index < otpInputs.length - 1) { 2894 otpInputs[index + 1].focus(); 2895 } 2896 2897 updateOTPValue(); 2898 }); 2899 2900 input.addEventListener('keydown', function(e) { 2901 if (e.key === 'Backspace' && !this.value && index > 0) { 2902 otpInputs[index - 1].focus(); 2903 } 2904 }); 2905 2906 input.addEventListener('paste', function(e) { 2907 e.preventDefault(); 2908 const pastedData = e.clipboardData.getData('text').replace(/\D/g, '').slice(0, 6); 2909 pastedData.split('').forEach((char, i) => { 2910 if (index + i < otpInputs.length) { 2911 otpInputs[index + i].value = char; 2912 } 2913 }); 2914 updateOTPValue(); 2915 if (index + pastedData.length < otpInputs.length) { 2916 otpInputs[Math.min(index + pastedData.length, otpInputs.length - 1)].focus(); 2917 } 2918 }); 2919 }); 2920 2921 function updateOTPValue() { 2922 const otp = Array.from(otpInputs).map(input => input.value).join(''); 2923 otpValueInput.value = otp; 2924 2925 otpInputs.forEach(input => { 2926 if (input.value) { 2927 input.classList.add('filled'); 2928 } else { 2929 input.classList.remove('filled'); 2930 } 2931 }); 2932 } 2933 2934 // OTP Resend timer 2935 let resendTimer = 60; 2936 const resendBtn = document.getElementById('otp-resend-btn'); 2937 const timerDisplay = document.getElementById('otpTimer'); 2938 2939 function updateResendTimer() { 2940 if (resendTimer > 0) { 2941 resendTimer--; 2942 resendBtn.disabled = true; 2943 if (timerDisplay) { 2944 timerDisplay.textContent = `${resendTimer} saniye sonra tekrar gönderebilirsiniz`; 2945 } 2946 setTimeout(updateResendTimer, 1000); 2947 } else { 2948 resendBtn.disabled = false; 2949 if (timerDisplay) { 2950 timerDisplay.textContent = ''; 2951 } 2952 } 2953 } 2954 2955 // ========== OTP Operations ========== 2956 2957 // OTP Resend button (AJAX) 2958 if (resendBtn) { 2959 resendBtn.addEventListener('click', async function() { 2960 if (this.disabled) return; 2961 2962 if (!savedFormData) { 2963 alert('Form verileri bulunamadı. Lütfen sayfayı yenileyin.'); 2964 return; 2965 } 2966 2967 // Loading state 2968 this.disabled = true; 2969 const originalText = this.textContent; 2970 this.textContent = 'Gönderiliyor...'; 2971 2972 try { 2973 const formData = new FormData(); 2974 // Copy all fields from savedFormData 2975 for (let [key, value] of savedFormData.entries()) { 2976 formData.append(key, value); 2977 } 2978 formData.append('step', 'send_otp'); 2979 2980 const response = await fetch('/accounts/register/', { 2981 method: 'POST', 2982 body: formData, 2983 headers: { 2984 'X-Requested-With': 'XMLHttpRequest', 2985 }, 2986 credentials: 'same-origin' 2987 }); 2988 2989 const data = await response.json(); 2990 2991 if (data.success) { 2992 // Timer'ı sıfırla 2993 resendTimer = 60; 2994 updateResendTimer(); 2995 } else { 2996 alert(data.message || 'OTP gönderilemedi. Lütfen tekrar deneyin.'); 2997 } 2998 } catch (error) { 2999 console.error('OTP resend hatası:', error); 3000 alert('Bir hata oluÅtu. Lütfen tekrar deneyin.'); 3001 } finally { 3002 this.disabled = false;
3003 this.textContent = originalText; 3004 } 3005 }); 3006 } 3007 3008 // OTP Form submit (AJAX) 3009 const otpForm = document.getElementById('otp-form'); 3010 if (otpForm) { 3011 otpForm.addEventListener('submit', async function(e) { 3012 e.preventDefault(); 3013 3014 const otp = otpValueInput.value; 3015 if (otp.length !== 6) { 3016 const errorDiv = document.getElementById('otpError'); 3017 errorDiv.textContent = 'Lütfen 6 haneli kodu eksiksiz girin'; 3018 errorDiv.style.display = 'block'; 3019 return false; 3020 } 3021 3022 if (!savedFormData) { 3023 alert('Form verileri bulunamadı. Lütfen sayfayı yenileyin.'); 3024 return false; 3025 } 3026 3027 // Loading state 3028 const verifyBtn = document.getElementById('otp-verify-btn'); 3029 if (verifyBtn) { 3030 verifyBtn.disabled = true; 3031 verifyBtn.textContent = 'DoÄrulanıyor...'; 3032 } 3033 3034 const errorDiv = document.getElementById('otpError'); 3035 errorDiv.style.display = 'none'; 3036 3037 try { 3038 const formData = new FormData(); 3039 // Copy all fields from savedFormData 3040 for (let [key, value] of savedFormData.entries()) { 3041 formData.append(key, value); 3042 } 3043 formData.append('step', 'verify_otp'); 3044 formData.append('otp', otp); 3045 3046 const response = await fetch('/accounts/register/', { 3047 method: 'POST', 3048 body: formData, 3049 headers: { 3050 'X-Requested-With': 'XMLHttpRequest', 3051 }, 3052 credentials: 'same-origin' 3053 }); 3054 3055 // Check if response is JSON 3056 const contentType = response.headers.get('content-type'); 3057 if (!contentType || !contentType.includes('application/json')) { 3058 // Backend HTML döndürmüÅ, bu bir hata 3059 throw new Error('Sunucudan beklenmeyen yanıt alındı. Lütfen sayfayı yenileyin.'); 3060 } 3061 3062 if (!response.ok) { 3063 throw new Error(`HTTP error! status: ${response.status}`); 3064 } 3065 3066 const data = await response.json(); 3067 3068 if (data.success && data.step === 'complete') { 3069 // Redirect to home 3070 window.location.href = data.redirect_url || '/'; 3071 } else { 3072 // Show error 3073 errorDiv.textContent = data.message || data.errors?.otp?.[0] || 'Geçersiz OTP kodu'; 3074 errorDiv.style.display = 'block'; 3075 3076 if (verifyBtn) { 3077 verifyBtn.disabled = false; 3078 verifyBtn.textContent = 'DoÄrula ve Kayıt Ol'; 3079 } 3080 } 3081 } catch (error) { 3082 console.error('OTP verify hatası:', error); 3083 errorDiv.textContent = error.message || 'Bir hata oluÅtu. Lütfen tekrar deneyin.'; 3084 errorDiv.style.display = 'block'; 3085 3086 if (verifyBtn) { 3087 verifyBtn.disabled = false; 3088 verifyBtn.textContent = 'DoÄrula ve Kayıt Ol'; 3089 } 3090 } 3091 3092 return false; 3093 }); 3094 } 3095 3096 // Show OTP modal if step is send_otp or verify_otp 3097 const currentStep = 'validate_info'; 3098 if (currentStep === 'send_otp' || currentStep === 'verify_otp') { 3099 const otpModal = document.getElementById('otpModal'); 3100 if (otpModal) { 3101 otpModal.classList.add('active'); 3102 3103 // Fill OTP form hidden inputs with form data from context 3104 const otpMemberType = document.getElementById('otp_member_type'); 3105 const otpFirstName = document.getElementById('otp_first_name'); 3106 const otpLastName = document.getElementById('otp_last_name'); 3107 const otpEmail = document.getElementById('otp_email'); 3108 const otpPhone = document.getElementById('otp_phone_number'); 3109 const otpPassword = document.getElementById('otp_password'); 3110 const otpPasswordConfirm = document.getElementById('otp_password_confirm'); 3111 3112 if (otpMemberType) otpMemberType.value = 'individual'; 3113 if (otpFirstName) otpFirstName.value = ''; 3114 if (otpLastName) otpLastName.value = ''; 3115 if (otpEmail) otpEmail.value = ''; 3116 if (otpPhone) otpPhone.value = ''; 3117 3118 // Password'ları form'dan al (eÄer hala form'da varsa) 3119 const passwordInput = document.getElementById('password'); 3120 const passwordConfirmInput = document.getElementById('password_confirm'); 3121 if (passwordInput && otpPassword) { 3122 otpPassword.value = passwordInput.value || ''; 3123 } 3124 if (passwordConfirmInput && otpPasswordConfirm) { 3125 otpPasswordConfirm.value = passwordConfirmInput.value || ''; 3126 } 3127 3128 // Kurumsal alanlar - form'dan veya template'den al 3129 if ('individual' === 'corporate') { 3130 const otpCompanyName = document.getElementById('otp_company_name'); 3131 const otpCorporateType = document.getElementById('otp_corporate_type'); 3132 const otpCompanyLicenseNo = document.getElementById('otp_company_license_no'); 3133 const otpSpkTcNo = document.getElementById('otp_spk_tc_no'); 3134 const corpTypeInput = document.getElementById('corporate_type'); 3135 const licenseInput = document.getElementById('company_license_no'); 3136 const spkTcInput = document.getElementById('spk_tc_no'); 3137 const corpForm = document.getElementById('form-corporate'); 3138 const companyNameInput = corpForm ? corpForm.querySelector('[name="company_name"]') : null; 3139 if (otpCompanyName) otpCompanyName.value = (companyNameInput && companyNameInput.value) || ''; 3140 if (otpCorporateType) otpCorporateType.value = (corpTypeInput && corpTypeInput.value) || 'emlak'; 3141 if (otpCompanyLicenseNo) otpCompanyLicenseNo.value = (licenseInput && licenseInput.value) || ''; 3142 if (otpSpkTcNo) otpSpkTcNo.value = (spkTcInput && spkTcInput.value) || ''; 3143 } 3144 3145 // Focus first OTP input 3146 setTimeout(() => { 3147 if (otpInputs.length > 0) { 3148 otpInputs[0].focus(); 3149 } 3150 }, 100); 3151 3152 // Start resend timer 3153 updateResendTimer(); 3154 } 3155 } 3156 3157 // Gizli alanların required'ını kaldır (her zaman) 3158 function removeRequiredFromHiddenFields() { 3159 const memberType = document.getElementById('member_type').value; 3160 const corporateFields = document.getElementById('corporate-fields'); 3161 3162 // Gizli kurumsal alanların required'ını kaldır (bireysel modda) 3163 if (memberType === 'individual' && corporateFields) { 3164 const corporateInputs = corporateFields.querySelectorAll('input, select, textarea');
3165 corporateInputs.forEach(input => { 3166 if (input.hasAttribute('required')) { 3167 input.setAttribute('data-was-required', 'true'); 3168 input.removeAttribute('required'); 3169 } 3170 }); 3171 } 3172 } 3173 3174 // Sayfa yüklendiÄinde ve tab deÄiÅtiÄinde çalıÅtır 3175 removeRequiredFromHiddenFields(); 3176 3177 // Gizli div'leri geçici olarak görünür yap (gizli div içindeki input'lar POST'ta gelmeyebilir) 3178 function makeHiddenDivsVisibleForSubmit() { 3179 console.log('[register.html] Gizli div\'leri geçici olarak görünür yapıyor...'); 3180 3181 // Tüm step div'lerini bul 3182 const stepValidateInfo = document.getElementById('step-validate-info'); 3183 const stepUploadMedia = document.getElementById('step-upload-media'); 3184 3185 // Gizli div'leri CSS ile görünmez yap ama DOM'da kalsınlar (POST'ta gelsinler) 3186 // position: absolute; left: -9999px; opacity: 0; ile görünmez yap ama DOM'da kalır 3187 if (stepValidateInfo && stepValidateInfo.style.display === 'none') { 3188 // Görünmez yap ama DOM'da kalsın (POST'ta gelsin) 3189 stepValidateInfo.style.position = 'absolute'; 3190 stepValidateInfo.style.left = '-9999px'; 3191 stepValidateInfo.style.opacity = '0'; 3192 stepValidateInfo.style.display = 'block'; // display:block yap ki POST'ta gelsin 3193 stepValidateInfo.style.visibility = 'hidden'; 3194 console.log('[register.html] step-validate-info görünmez yapıldı ama DOM\'da kaldı'); 3195 } 3196 3197 if (stepUploadMedia && stepUploadMedia.style.display === 'none') { 3198 stepUploadMedia.style.position = 'absolute'; 3199 stepUploadMedia.style.left = '-9999px'; 3200 stepUploadMedia.style.opacity = '0'; 3201 stepUploadMedia.style.display = 'block'; 3202 stepUploadMedia.style.visibility = 'hidden'; 3203 console.log('[register.html] step-upload-media görünmez yapıldı ama DOM\'da kaldı'); 3204 } 3205 3206 console.log('[register.html] Gizli div\'ler görünmez yapıldı ama DOM\'da kaldı (POST\'ta gelecek)'); 3207 } 3208 3209 // Form submit - Gizli div'leri görünür yap, backend validasyonuna güven 3210 const form = document.getElementById('register-form'); 3211 if (form) { 3212 form.addEventListener('submit', function(e) { 3213 console.log('[register.html] Form submit ediliyor...'); 3214 3215 // Gizli alanların required'ını kaldır 3216 removeRequiredFromHiddenFields(); 3217 3218 // Gizli div'leri geçici olarak görünür yap (POST'ta gelsinler) 3219 makeHiddenDivsVisibleForSubmit(); 3220 3221 const currentStepValue = document.getElementById('step').value; 3222 console.log('[register.html] Current step:', currentStepValue); 3223 3224 // Form verilerini logla (debug için) 3225 const formData = new FormData(form); 3226 console.log('[register.html] POST\'ta gönderilecek alanlar:'); 3227 for (let [key, value] of formData.entries()) { 3228 if (key.includes('password')) { 3229 console.log(` - ${key}: *** (${value.length} karakter)`); 3230 } else { 3231 console.log(` - ${key}: ${value}`); 3232 } 3233 } 3234 3235 // Formu submit et - backend validasyonu yapacak 3236 // Backend'den dönen hatalar template'de gösterilecek 3237 }); 3238 } 3239 3240 // ========== Kayıt adres: İl / İlçe / Mahalle (DanıÅman & Kurumsal) ========== 3241 function initRegisterAddress(prefix) { 3242 var il = document.getElementById('reg_' + prefix + '_il'); 3243 var ilce = document.getElementById('reg_' + prefix + '_ilce'); 3244 var mahalle = document.getElementById('reg_' + prefix + '_mahalle'); 3245 if (!il || !ilce || !mahalle) return; 3246 function hid(id) { return document.getElementById('reg_' + prefix + '_' + id); } 3247 function loadTowns(cityId) { 3248 resetLocationSelect(mahalle, 'Mahalle Seçiniz'); 3249 if (!cityId) { 3250 resetLocationSelect(ilce, 'İlçe Seçiniz'); 3251 hid('city_id').value = ''; 3252 hid('city_name').value = ''; 3253 return; 3254 } 3255 hid('city_id').value = cityId; 3256 hid('city_name').value = (il.options[il.selectedIndex] && il.options[il.selectedIndex].text) ? il.options[il.selectedIndex].text.trim() : ''; 3257 destroyLocationSelect2(ilce); 3258 ilce.innerHTML = '<option value="">Yükleniyor...</option>'; 3259 ilce.disabled = true; 3260 initLocationSelect2(ilce, 'İlçe Seçiniz', true); 3261 fetch('/api/towns/?CityId=' + encodeURIComponent(cityI
3261d)).then(function(r) { return r.json(); }).then(function(data) { 3262 var list = (data && data.ilceler) ? data.ilceler : (Array.isArray(data) ? data : []); 3263 destroyLocationSelect2(ilce); 3264 ilce.innerHTML = '<option value="">İlçe Seçiniz</option>'; 3265 list.forEach(function(t) { var o = document.createElement('option'); o.value = t.Id; o.textContent = t.Proparcel_text || t.Id; ilce.appendChild(o); }); 3266 initLocationSelect2(ilce, 'İlçe Seçiniz', false); 3267 bindLocationSelectHandler(ilce, prefix + '-ilce', loadQuarters); 3268 }).catch(function() { 3269 initLocationSelect2(ilce, 'İlçe Seçiniz', false); 3270 bindLocationSelectHandler(ilce, prefix + '-ilce', loadQuarters); 3271 }); 3272 } 3273 function loadQuarters(townId) { 3274 if (!townId) { 3275 resetLocationSelect(mahalle, 'Mahalle Seçiniz'); 3276 hid('district_id').value = ''; 3277 hid('district_name').value = ''; 3278 return; 3279 } 3280 hid('district_id').value = townId; 3281 hid('district_name').value = (ilce.options[ilce.selectedIndex] && ilce.options[ilce.selectedIndex].text) ? ilce.options[ilce.selectedIndex].text.trim() : ''; 3282 destroyLocationSelect2(mahalle); 3283 mahalle.innerHTML = '<option value="">Yükleniyor...</option>'; 3284 mahalle.disabled = true; 3285 initLocationSelect2(mahalle, 'Mahalle Seçiniz', true); 3286 fetch('/api/quarters/?TownId=' + encodeURIComponent(townId)).then(function(r) { return r.json(); }).then(function(data) { 3287 var list = Array.isArray(data) ? data : (data && data.quarters ? data.quarters : []); 3288 destroyLocationSelect2(mahalle); 3289 mahalle.innerHTML = '<option value="">Mahalle Seçiniz</option>'; 3290 list.forEach(function(q) { 3291 var o = document.createElement('option'); 3292 o.value = (q.list_key != null && q.list_key !== '') ? q.list_key : q.Id; 3293 if (q.Id != null) o.dataset.quarterId = String(q.Id); 3294 if (q.Proparcel_value != null) o.dataset.proparcelValue = String(q.Proparcel_value); 3295 o.textContent = (q.display_text || q.Tkgm_text || q.Proparcel_text || q.Id); 3296 mahalle.appendChild(o); 3297 }); 3298 initLocationSelect2(mahalle, 'Mahalle Seçiniz', false); 3299 bindLocationSelectHandler(mahalle, prefix + '-mahalle', syncMahalleHidden); 3300 }).catch(function() { 3301 initLocationSelect2(mahalle, 'Mahalle Seçiniz', false); 3302 bindLocationSelectHandler(mahalle, prefix + '-mahalle', syncMahalleHidden); 3303 }); 3304 } 3305 function syncMahalleHidden(val) { 3306 var opt = mahalle.options[mahalle.selectedIndex]; 3307 hid('quarter_id').value = (opt && opt.dataset.quarterId) ? opt.dataset.quarterId : (val || ''); 3308 hid('quarter_name').value = (opt && opt.text) ? opt.text.trim() : ''; 3309 hid('quarter_value').value = (opt && opt.dataset.proparcelValue) ? opt.dataset.proparcelValue : ''; 3310 } 3311 resetLocationSelect(ilce, 'İlçe Seçiniz'); 3312 resetLocationSelect(mahalle, 'Mahalle Seçiniz'); 3313 fetch('/api/cities/').then(function(r) { return r.json(); }).then(function(data) { 3314 if (!Array.isArray(data) || data.length === 0) { 3315 initLocationSelect2(il, 'İl Seçiniz', false); 3316 bindLocationSelectHandler(il, prefix + '-il', loadTowns); 3317 return; 3318 } 3319 destroyLocationSelect2(il); 3320 il.innerHTML = '<option value="">İl Seçiniz</option>'; 3321 data.forEach(function(c) { var o = document.createElement('option'); o.value = c.Id; o.textContent = c.Proparcel_text || c.Id; il.appendChild(o); }); 3322 initLocationSelect2(il, 'İl Seçiniz', false); 3323 bindLocationSelectHandler(il, prefix + '-il', loadTowns); 3324 }).catch(function() { 3325 initLocationSelect2(il, 'İl Seçiniz', false); 3326 bindLocationSelectHandler(il, prefix + '-il', loadTowns); 3327 }); 3328 } 3329 3330 // ========== Uzmanlık Bölgeleri (DanıÅman & Kurumsal) ========== 3331 3332 // Show expertise areas step 3333 async function showExpertiseAreasStep(formType) { 3334 const validateStep = document.getElementById(`step-validate-info-${formType}`); 3335 const uploadStep = document.getElementById(`step-upload-media-${formType}`); 3336 const expertiseStep = document.getElementById(`step-expertise-areas-${formType}`); 3337 3338 if (validateStep) validateStep.style.display = 'none'; 3339 if (uploadStep) uploadStep.style.display = 'none'; 3340 if (expertiseStep) expertiseStep.style.display = 'block'; 3341 3342 initExpertiseAreas(formType); 3343 } 3344 3345 // SPK Kurumsal: sadece il seçimi (max 5) 3346 function initExpertiseCitiesCorporate() { 3347 const ilSelect = document.getElementById('expertise_il_only_corporate'); 3348 const hiddenInput = document.getElementById('expertise_cities_corporate'); 3349 const listContainer = document.getElementById('expertise-list-cities-corporate'); 3350 const hintEl = document.getElementById('expertise-hint-cities-corporate'); 3351 const noMsgEl = document.getElementById('no-expertise-cities-msg-corporate'); 3352 if (!ilSelect || !listContainer || ilSelect.dataset.initialized) return; 3353 ilSelect.dataset.initialized = 'true'; 3354 3355 function getCityValues() { 3356 if (!hiddenInput || !hiddenInput.value) return []; 3357 return hiddenInput.value.split(',').map(s =>
3357 s.trim()).filter(Boolean).map(s => parseInt(s, 10)).filter(n => Number.isFinite(n)); 3358 } 3359 function setCityValues(values) { 3360 if (hiddenInput) hiddenInput.value = values.join(','); 3361 } 3362 function showHint(msg, isError) { 3363 if (!hintEl) return; 3364 hintEl.style.display = msg ? 'block' : 'none'; 3365 hintEl.textContent = msg || ''; 3366 hintEl.style.color = isError ? 'var(--danger, #ef4444)' : 'var(--success, #22c55e)'; 3367 hintEl.style.background = isError ? 'rgba(239, 68, 68, 0.1)' : 'rgba(34, 197, 94, 0.1)'; 3368 } 3369 function addCity(cityId, cityName) { 3370 const values = getCityValues(); 3371 if (values.includes(cityId)) { 3372 showHint('Bu il zaten eklendi.', true); 3373 return false; 3374 } 3375 if (values.length >= 5) { 3376 showHint('En fazla 5 il ekleyebilirsiniz.', true); 3377 return false; 3378 } 3379 values.push(cityId); 3380 setCityValues(values); 3381 const item = document.createElement('div'); 3382 item.className = 'expertise-item'; 3383 item.dataset.cityId = String(cityId); 3384 item.style.cssText = 'display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; background: rgba(34, 197, 94, 0.08); border: 1px solid rgba(34, 197, 94, 0.2); border-radius: 8px; margin-bottom: 8px;'; 3385 item.innerHTML = ` 3386 <div style="flex: 1; font-weight: 600; color: var(--text); font-size: 0.95rem;">${cityName}</div> 3387 <button type="button" class="remove-expertise-city-btn" data-city-id="${cityId}" style="border: none; background: rgba(239, 68, 68, 0.1); color: #ef4444; cursor: pointer; padding: 8px; border-radius: 6px;"><i class="fas fa-times"></i></button> 3388 `; 3389 listContainer.insertBefore(item, noMsgEl); 3390 noMsgEl.style.display = 'none'; 3391 showHint(`${cityName} eklendi. (${values.length}/5)`, false); 3392 return true; 3393 } 3394 function removeCity(cityId) { 3395 const values = getCityValues().filter(v => v !== cityId); 3396 setCityValues(values); 3397 const item = listContainer.querySelector(`.expertise-item[data-city-id="${cityId}"]`); 3398 if (item) item.remove(); 3399 noMsgEl.style.display = getCityValues().length === 0 ? 'block' : 'none'; 3400 showHint('', false); 3401 } 3402 listContainer.addEventListener('click', function(e) { 3403 const btn = e.target.closest('.remove-expertise-city-btn'); 3404 if (!btn) return; 3405 const cid = parseInt(btn.dataset.cityId, 10); 3406 if (Number.isFinite(cid)) removeCity(cid); 3407 }); 3408 fetch('/api/cities/').then(r => r.json()).then(data => { 3409 if (!Array.isArray(data)) return; 3410 destroyLocationSelect2(ilSelect); 3411 ilSelect.innerHTML = '<option value="">İl Seçiniz (seçtiÄinizde listeye eklenir)</option>'; 3412 data.forEach(c => { 3413 const o = document.createElement('option'); 3414 o.value = c.Id; 3415 o.textContent = c.Proparcel_text || c.Id; 3416 ilSelect.appendChild(o); 3417 }); 3418 initLocationSelect2(ilSelect, 'İl Seçiniz (seçtiÄinizde listeye eklenir)', false); 3419 }).catch(() => { initLocationSelect2(ilSelect, 'İl Seçiniz (seçtiÄinizde listeye eklenir)', false); }); 3420 ilSelect.addEventListener('change', function() { 3421 const opt = this.options[this.selectedIndex]; 3422 if (!opt || !opt.value) return; 3423 const cityId = parseInt(opt.value, 10); 3424 const cityName = opt.textContent || opt.value; 3425 if (Number.isFinite(cityId)) { 3426 if (addCity(cityId, cityName)) clearLocationSelect2Value(this); 3427 } 3428 }); 3429 } 3430 3431 // SPK DanıÅman: sadece il seçimi (max 5) - expert firmaya baÄlı danıÅmanlar için 3432 function initExpertiseCitiesConsultant() { 3433 const ilSelect = document.getElementById('expertise_il_only_consultant'); 3434 const hiddenInput = document.getElementById('expertise_cities_consultant'); 3435 const listContainer = document.getElementById('expertise-list-cities-consultant'); 3436 const hintEl = document.getElementById('expertise-hint-cities-consultant'); 3437 const noMsgEl = document.getElementById('no-expertise-cities-msg-consultant'); 3438 if (!ilSelect || !listContainer || ilSelect.dataset.initialized) return; 3439 ilSelect.dataset.initialized = 'true'; 3440 function getCityValues() { 3441 if (!hiddenInput || !hiddenInput.value) return []; 3442 return hiddenInput.value.split(',').map(s =>
3442 s.trim()).filter(Boolean).map(s => parseInt(s, 10)).filter(n => Number.isFinite(n)); 3443 } 3444 function setCityValues(values) { 3445 if (hiddenInput) hiddenInput.value = values.join(','); 3446 } 3447 function showHint(msg, isError) { 3448 if (!hintEl) return; 3449 hintEl.style.display = msg ? 'block' : 'none'; 3450 hintEl.textContent = msg || ''; 3451 hintEl.style.color = isError ? 'var(--danger, #ef4444)' : 'var(--success, #22c55e)'; 3452 hintEl.style.background = isError ? 'rgba(239, 68, 68, 0.1)' : 'rgba(34, 197, 94, 0.1)'; 3453 } 3454 function addCity(cityId, cityName) { 3455 const values = getCityValues(); 3456 if (values.includes(cityId)) { showHint('Bu il zaten eklendi.', true); return false; } 3457 if (values.length >= 5) { showHint('En fazla 5 il ekleyebilirsiniz.', true); return false; } 3458 values.push(cityId); 3459 setCityValues(values); 3460 const item = document.createElement('div'); 3461 item.className = 'expertise-item'; 3462 item.dataset.cityId = String(cityId); 3463 item.style.cssText = 'display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; background: rgba(34, 197, 94, 0.08); border: 1px solid rgba(34, 197, 94, 0.2); border-radius: 8px; margin-bottom: 8px;'; 3464 item.innerHTML = `<div style="flex: 1; font-weight: 600; color: var(--text); font-size: 0.95rem;">${cityName}</div><button type="button" class="remove-expertise-city-btn" data-city-id="${cityId}" style="border: none; background: rgba(239, 68, 68, 0.1); color: #ef4444; cursor: pointer; padding: 8px; border-radius: 6px;"><i class="fas fa-times"></i></button>`; 3465 listContainer.insertBefore(item, noMsgEl); 3466 noMsgEl.style.display = 'none'; 3467 showHint(`${cityName} eklendi. (${values.length}/5)`, false); 3468 return true; 3469 } 3470 function removeCity(cityId) { 3471 const values = getCityValues().filter(v => v !== cityId); 3472 setCityValues(values); 3473 const item = listContainer.querySelector(`.expertise-item[data-city-id="${cityId}"]`); 3474 if (item) item.remove(); 3475 noMsgEl.style.display = getCityValues().length === 0 ? 'block' : 'none'; 3476 showHint('', false); 3477 } 3478 listContainer.addEventListener('click', function(e) { 3479 const btn = e.target.closest('.remove-expertise-city-btn'); 3480 if (!btn) return; 3481 const cid = parseInt(btn.dataset.cityId, 10); 3482 if (Number.isFinite(cid)) removeCity(cid); 3483 }); 3484 fetch('/api/cities/').then(r => r.json()).then(data => { 3485 if (!Array.isArray(data)) return; 3486 destroyLocationSelect2(ilSelect); 3487 ilSelect.innerHTML = '<option value="">İl Seçiniz (seçtiÄinizde listeye eklenir)</option>'; 3488 data.forEach(c => { 3489 const o = document.createElement('option'); 3490 o.value = c.Id; 3491 o.textContent = c.Proparcel_text || c.Id; 3492 ilSelect.appendChild(o); 3493 }); 3494 initLocationSelect2(ilSelect, 'İl Seçiniz (seçtiÄinizde listeye eklenir)', false); 3495 }).catch(() => { initLocationSelect2(ilSelect, 'İl Seçiniz (seçtiÄinizde listeye eklenir)', false); }); 3496 ilSelect.addEventListener('change', function() { 3497 const opt = this.options[this.selectedIndex]; 3498 if (!opt || !opt.value) return; 3499 const cityId = parseInt(opt.value, 10); 3500 const cityName = opt.textContent || opt.value; 3501 if (Number.isFinite(cityId)) { 3502 if (addCity(cityId, cityName)) clearLocationSelect2Value(this); 3503 } 3504 }); 3505 } 3506 3507 // Expertise areas management 3508 function initExpertiseAreas(formType) { 3509 // DanıÅman SPK (buton seçimi veya SPK firma): sadece il seçimi (Ana Uzmanlık Bölgeleriniz) 3510 if (formType === 'consultant') { 3511 const consultantType = (document.getElementById('consultant_type') || {}).value || 'emlak'; 3512 if (consultantType === 'lihkab') { 3513 const spkDiv = document.getElementById('expertise-consultant-spk'); 3514 const emlakDiv = document.getElementById('expertise-consultant-emlak'); 3515 if (spkDiv) spkDiv.style.display = 'none'; 3516 if (emlakDiv) emlakDiv.style.display = 'none'; 3517 return; 3518 } 3519 const isConsultantSpk = shouldConsultantUseSpkFlow(consultantType); 3520 const spkDiv = document.getElementById('expertise-consultant-spk'); 3521 const emlakDiv = document.getElementById('expertise-consultant-emlak'); 3522 if (spkDiv) spkDiv.style.display = isConsultantSpk ? 'block' : 'none'; 3523 if (emlakDiv) emlakDiv.style.display = isConsultantSpk ? 'none' : 'block'; 3524 if (isConsultantSpk) { 3525 initExpertiseCitiesConsultant(); 3526 return; 3527 } 3528 } 3529 // Kurumsal SPK: sadece il seçimi (Ana Uzmanlık Bölgeleriniz) 3530 if (formType === 'corporate') { 3531 const corpType = (document.getElementById('corporate_type') || {}).value || 'emlak'; 3532 const spkDiv = document.getElementById('expertise-corporate-spk'); 3533 const emlakDiv = document.getElementById('expertise-corporate-emlak'); 3534 if (spkDiv) spkDiv.style.display = corpType === 'spk' ? 'block' : 'none'; 3535 if (emlakDiv) emlakDiv.style.display = corpType === 'spk' ? 'none' : (corpType === 'lihkab' ? 'none' : 'block'); 3536 if (corpType === 'lihkab') { 3537 return; 3538 } 3539 if (corpType === 'spk') { 3540 initExpertiseCitiesCorporate(); 3541 return; 3542 } 3543 } 3544 3545 const ilSelect = document.getElementById(`expertise_il_${formType}`); 3546 const ilceSelect = document.getElementById(`expertise_ilce_${formType}`); 3547 const mahalleSelect = document.getElementById(`expertise_mahalle_${formType}`); 3548 const hiddenInput = document.getElementById(`expertise_quarters_${formType}`); 3549 const listContainer = document.getElementById(`expertise-list-${formType}`); 3550 const hintEl = document.getElementById(`expertise-hint-${formType}`); 3551 const noMsgEl = document.getElementById(`no-expertise-msg-${formType}`); 3552 3553 if (!ilSelect || ilSelect.dataset.initialized) return; 3554 ilSelect.dataset.initialized = 'true'; 3555 resetLocationSelect(ilceSelect, 'İlçe Seçiniz'); 3556 resetLocationSelect(mahalleSelect, 'Mahalle Seçiniz'); 3557 3558 // Cache for selected city/district names 3559 let selectedCityName = ''; 3560 let selectedDistrictName = ''; 3561 3562 function getExpertiseValues() { 3563 if (!hiddenInput || !hiddenInput.value) return []; 3564 return hiddenInput.value.split(',').map(s =>
3564 s.trim()).filter(Boolean).map(s => parseInt(s, 10)).filter(n => Number.isFinite(n)); 3565 } 3566 3567 function setExpertiseValues(values) { 3568 if (hiddenInput) hiddenInput.value = values.join(','); 3569 } 3570 3571 function showHint(msg, isError) { 3572 if (!hintEl) return; 3573 if (!msg) { 3574 hintEl.style.display = 'none'; 3575 hintEl.textContent = ''; 3576 return; 3577 } 3578 hintEl.style.display = 'block'; 3579 hintEl.textContent = msg; 3580 hintEl.style.color = isError ? 'var(--danger, #ef4444)' : 'var(--success, #22c55e)'; 3581 hintEl.style.background = isError ? 'rgba(239, 68, 68, 0.1)' : 'rgba(34, 197, 94, 0.1)'; 3582 } 3583 3584 function updateNoMessage() { 3585 const values = getExpertiseValues(); 3586 if (noMsgEl) { 3587 noMsgEl.style.display = values.length === 0 ? 'block' : 'none'; 3588 } 3589 } 3590 3591 function addExpertiseArea(proparcelValue, mahalleName, districtName, cityName) { 3592 const values = getExpertiseValues(); 3593 if (values.includes(proparcelValue)) { 3594 showHint('Bu mahalle zaten eklendi.', true); 3595 return false; 3596 } 3597 if (values.length >= 5) { 3598 showHint('En fazla 5 uzmanlık bölgesi ekleyebilirsiniz.', true); 3599 return false; 3600 } 3601 3602 values.push(proparcelValue); 3603 setExpertiseValues(values); 3604 3605 // Create list item 3606 const item = document.createElement('div'); 3607 item.className = 'expertise-item'; 3608 item.dataset.qv = String(proparcelValue); 3609 item.style.cssText = 'display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; background: rgba(34, 197, 94, 0.08); border: 1px solid rgba(34, 197, 94, 0.2); border-radius: 8px; margin-bottom: 8px;'; 3610 3611 const locationText = [districtName, cityName].filter(Boolean).join(', '); 3612 item.innerHTML = ` 3613 <div style="flex: 1;"> 3614 <div style="font-weight: 600; color: var(--text); font-size: 0.95rem;">${mahalleName}</div> 3615 <div style="font-size: 0.85rem; color: var(--text-secondary); margin-top: 2px;">${locationText}</div> 3616 </div> 3617 <button type="button" class="remove-expertise-btn" data-qv="${proparcelValue}" style="border: none; background: rgba(239, 68, 68, 0.1); color: #ef4444; cursor: pointer; padding: 8px; border-radius: 6px; transition: all 0.2s;"> 3618 <i class="fas fa-times"></i> 3619 </button> 3620 `; 3621 3622 listContainer.insertBefore(item, noMsgEl); 3623 updateNoMessage(); 3624 showHint(`${mahalleName} eklendi. (${values.length}/5)`, false); 3625 return true; 3626 } 3627 3628 function removeExpertiseArea(proparcelValue) { 3629 const values = getExpertiseValues().filter(v => v !== proparcelValue); 3630 setExpertiseValues(values); 3631 3632 const item = listContainer.querySelector(`.expertise-item[data-qv="${proparcelValue}"]`); 3633 if (item) item.remove(); 3634 3635 updateNoMessage(); 3636 showHint('', false); 3637 } 3638 3639 // Event delegation for remove buttons 3640 listContainer.addEventListener('click', function(e) { 3641 const btn = e.target.closest('.remove-expertise-btn'); 3642 if (!btn) return; 3643 const qv = parseInt(btn.dataset.qv, 10); 3644 if (Number.isFinite(qv)) removeExpertiseArea(qv); 3645 }); 3646 3647 // Load cities 3648 fetch('/api/cities/').then(r => r.json()).then(data => { 3649 if (!Array.isArray(data)) return; 3650 destroyLocationSelect2(ilSelect); 3651 ilSelect.innerHTML = '<option value="">İl Seçiniz</option>'; 3652 data.forEach(c => { 3653 const o = document.createElement('option'); 3654 o.value = c.Id; 3655 o.textContent = c.Proparcel_text || c.Id; 3656 ilSelect.appendChild(o); 3657 }); 3658 initLocationSelect2(ilSelect, 'İl Seçiniz', false); 3659 }).catch(() => { initLocationSelect2(ilSelect, 'İl Seçiniz', false); }); 3660 3661 // City change -> load towns (il seçimi sonrası resetleme yok) 3662 ilSelect.addEventListener('change', function() { 3663 const cityId = this.value; 3664 selectedCityName = this.options[this.selectedIndex]?.text || ''; 3665 3666 resetLocationSelect(ilceSelect, 'Yükleniyor...'); 3667 resetLocationSelect(mahalleSelect, 'Mahalle Seçiniz'); 3668 selectedDistrictName = ''; 3669 3670 if (!cityId) { 3671 resetLocationSelect(ilceSelect, 'İlçe Seçiniz'); 3672 return; 3673 } 3674 3675 fetch(`/api/towns/?CityId=${encodeURIComponent(cityI
3675d)}`).then(r => r.json()).then(data => { 3676 const list = (data && data.ilceler) ? data.ilceler : (Array.isArray(data) ? data : []); 3677 destroyLocationSelect2(ilceSelect); 3678 ilceSelect.innerHTML = '<option value="">İlçe Seçiniz</option>'; 3679 list.forEach(t => { 3680 const o = document.createElement('option'); 3681 o.value = t.Id; 3682 o.textContent = t.Proparcel_text || t.Id; 3683 ilceSelect.appendChild(o); 3684 }); 3685 initLocationSelect2(ilceSelect, 'İlçe Seçiniz', false); 3686 }).catch(() => { 3687 initLocationSelect2(ilceSelect, 'İlçe Seçiniz', false); 3688 }); 3689 }); 3690 3691 // District change -> load quarters (ilçe seçimi sonrası resetleme yok) 3692 ilceSelect.addEventListener('change', function() { 3693 const townId = this.value; 3694 selectedDistrictName = this.options[this.selectedIndex]?.text || ''; 3695 3696 if (!townId) { 3697 resetLocationSelect(mahalleSelect, 'Mahalle Seçiniz'); 3698 return; 3699 } 3700 3701 destroyLocationSelect2(mahalleSelect); 3702 mahalleSelect.innerHTML = '<option value="">Yükleniyor...</option>'; 3703 mahalleSelect.disabled = true; 3704 initLocationSelect2(mahalleSelect, 'Mahalle Seçiniz', true); 3705 3706 fetch(`/api/quarters/?TownId=${encodeURIComponent(townId)}`).then(r => r.json()).then(data => { 3707 const list = Array.isArray(data) ? data : (data && data.quarters ? data.quarters : []); 3708 destroyLocationSelect2(mahalleSelect); 3709 mahalleSelect.innerHTML = '<option value="">Mahalle Seçiniz (seçtiÄinizde listeye eklenir)</option>'; 3710 list.forEach(q => { 3711 const o = document.createElement('option'); 3712 o.value = (q.list_key != null && q.list_key !== '') ? q.list_key : q.Id; 3713 if (q.Id != null) o.dataset.quarterId = String(q.Id); 3714 if (q.Proparcel_value != null) o.dataset.proparcelValue = String(q.Proparcel_value); 3715 o.dataset.mahalleName = (q.display_text || q.Tkgm_text || q.Proparcel_text || q.Id); 3716 o.textContent = o.dataset.mahalleName; 3717 mahalleSelect.appendChild(o); 3718 }); 3719 initLocationSelect2(mahalleSelect, 'Mahalle Seçiniz (seçtiÄinizde listeye eklenir)', false); 3720 }).catch(() => { 3721 initLocationSelect2(mahalleSelect, 'Mahalle Seçiniz', false); 3722 }); 3723 }); 3724 3725 // Quarter selection -> add to list (mahalle seçildiÄinde listeye ekle, seçimi resetleme) 3726 mahalleSelect.addEventListener('change', function() { 3727 const opt = this.options[this.selectedIndex]; 3728 if (!opt || !opt.value) return; 3729 3730 const proparcelValue = parseInt(opt.dataset.proparcelValue || '0', 10); 3731 const mahalleName = opt.dataset.mahalleName || opt.textContent; 3732 3733 if (proparcelValue && Number.isFinite(proparcelValue)) { 3734 const added = addExpertiseArea(proparcelValue, mahalleName, selectedDistrictName, selectedCityName); 3735 if (added) { 3736 clearLocationSelect2Value(this); 3737 } 3738 } 3739 }); 3740 } 3741 3742 // Expertise step button handlers -> go to OTP 3743 const continueExpertiseConsultant = document.getElementById('continue-expertise-btn-consultant'); 3744 const skipExpertiseConsultant = document.getElementById('skip-expertise-btn-consultant'); 3745 const continueExpertiseCorporate = document.getElementById('continue-expertise-btn-corporate'); 3746 const skipExpertiseCorporate = document.getElementById('skip-expertise-btn-corporate'); 3747 3748 function goToOTPStep(formType) { 3749 finalizeRegistrationAfterExpertise(formType); 3750 } 3751 3752 if (continueExpertiseConsultant) { 3753 continueExpertiseConsultant.addEventListener('click', function(e) { 3754 e.preventDefault(); 3755 goToOTPStep('consultant'); 3756 }); 3757 } 3758 3759 if (skipExpertiseConsultant) { 3760 skipExpertiseConsultant.addEventListener('click', function(e) { 3761 e.preventDefault(); 3762 goToOTPStep('consultant'); 3763 }); 3764 } 3765 3766 if (continueExpertiseCorporate) { 3767 continueExpertiseCorporate.addEventListener('click', function(e) { 3768 e.preventDefault(); 3769 goToOTPStep('corporate'); 3770 }); 3771 } 3772 3773 if (skipExpertiseCorporate) { 3774 skipExpertiseCorporate.addEventListener('click', function(e) { 3775 e.preventDefault(); 3776 goToOTPStep('corporate'); 3777 }); 3778 } 3779 3780 // ============================================ 3781 // MEZUNİYET BİLGİLERİ YÃNETİMİ 3782 // ============================================ 3783
3784 // Ãniversite ve bölüm verileri cache 3785 let universitiesCache = null; 3786 let departmentsCache = { 1: null, 2: null }; // degree_level: data 3787 let universitiesFetchError = null; 3788 const educationApiBase = '/api/education'; 3789 3790 function isSelect2Ready() { 3791 return !!(window.jQuery && window.jQuery.fn && typeof window.jQuery.fn.select2 === 'function'); 3792 } 3793 3794 function initSelect2(selectEl, placeholderText) { 3795 if (!selectEl || !isSelect2Ready()) return; 3796 const $select = window.jQuery(selectEl); 3797 if ($select.data('select2')) { 3798 $select.select2('destroy'); 3799 } 3800 $select.select2({ 3801 width: '100%', 3802 placeholder: placeholderText || 'Seçiniz', 3803 allowClear: true, 3804 language: 'tr' 3805 }); 3806 } 3807 3808 function refreshSelect2(selectEl) { 3809 if (!selectEl || !isSelect2Ready()) return; 3810 const $select = window.jQuery(selectEl); 3811 if ($select.data('select2')) { 3812 $select.trigger('change.select2'); 3813 } 3814 } 3815 3816 function destroyLocationSelect2(selectEl) { 3817 if (!selectEl || !isSelect2Ready()) return; 3818 const $select = window.jQuery(selectEl); 3819 if ($select.data('select2')) { 3820 $select.select2('destroy'); 3821 } 3822 } 3823 3824 function initLocationSelect2(selectEl, placeholderText, isDisabled) { 3825 if (!selectEl) return; 3826 destroyLocationSelect2(selectEl); 3827 selectEl.disabled = !!isDisabled; 3828 if (!isSelect2Ready() || isDisabled) return; 3829 window.jQuery(selectEl).prop('disabled', false).select2({ 3830 width: '100%', 3831 placeholder: placeholderText || 'Seçiniz', 3832 allowClear: true, 3833 language: 'tr', 3834 dropdownCssClass: 'pp-auth-select2-dropdown', 3835 selectionCssClass: 'pp-auth-select2-selection', 3836 }); 3837 } 3838 3839 function resetLocationSelect(selectEl, placeholderText) { 3840 if (!selectEl) return; 3841 destroyLocationSelect2(selectEl); 3842 selectEl.innerHTML = '<option value="">' + placeholderText + '</option>'; 3843 selectEl.disabled = true; 3844 initLocationSelect2(selectEl, placeholderText, true); 3845 } 3846 3847 function clearLocationSelect2Value(selectEl) { 3848 if (!selectEl) return; 3849 selectEl.value = ''; 3850 if (isSelect2Ready() && window.jQuery(selectEl).data('select2')) { 3851 window.jQuery(selectEl).val('').trigger('change.select2'); 3852 } 3853 } 3854 3855 function bindLocationSelectHandler(selectEl, namespace, onValueChange) { 3856 if (!selectEl || typeof onValueChange !== 'function') return; 3857 var ns = namespace || 'loc'; 3858 var lastVal = null; 3859 function invoke(val) { 3860 val = String(val || ''); 3861 if (val === lastVal) return; 3862 lastVal = val; 3863 onValueChange(val); 3864 } 3865 if (isSelect2Ready()) { 3866 var $select = window.jQuery(selectEl); 3867 $select.off('select2:select.' + ns + ' change.' + ns) 3868 .on('select2:select.' + ns, function(e) { 3869 var val = (e.params && e.params.data != null) ? e.params.data.id : selectEl.value; 3870 invoke(val); 3871 }) 3872 .on('change.' + ns, function() { 3873 invoke(window.jQuery(this).val()); 3874 }); 3875 } else { 3876 selectEl.addEventListener('change', function() { 3877 invoke(this.value); 3878 }); 3879 } 3880 } 3881 3882 function showUniversityError(errorEl, message) { 3883 if (!errorEl) return; 3884 errorEl.textContent = message; 3885 errorEl.style.display = 'block'; 3886 } 3887 3888 function clearUniversityError(errorEl) { 3889 if (!errorEl) return; 3890 errorEl.textContent = ''; 3891 errorEl.style.display = 'none'; 3892 } 3893 3894 function getEducationApiUrl(endpoint) { 3895 return `${educationApiBase}/${endpoint}/`; 3896 } 3897 3898 // Ãniversiteleri yükle 3899 async function loadUniversities() { 3900 if (universitiesCache) return universitiesCache; 3901 try { 3902 const response = await fetch(getEducationApiUrl('universities'), { 3903 headers: { 'X-Requested-With': 'XMLHttpRequest' } 3904 }); 3905 if (!response.ok) { 3906 throw new Error(`HTTP ${response.status}`); 3907 } 3908 const data = await response.json(); 3909 universitiesCache = Array.isArray(data.universities) ? data.universities : []; 3910 universitiesFetchError = null; 3911 return universitiesCache; 3912 } catch (error) { 3913 console.error('Ãniversiteler yüklenemedi:', error); 3914 universitiesFetchError = error; 3915 return []; 3916 } 3917 } 3918 3919 // Bölümleri yükle (degree_level: 1=Lisans, 2=Ãn Lisans) 3920 async function loadDepartments(degreeLevel) { 3921 if (departmentsCache[degreeLevel]) return departmentsCache[degreeLevel]; 3922 try { 3923 const response = await fetch(`${getEducationApiUrl('departments')}?degree_level=${degreeLevel}`, { 3924 headers: { 'X-Requested-With': 'XMLHttpRequest' } 3925 }); 3926 if (!response.ok) { 3927 throw new Error(`HTTP ${response.status}`); 3928 } 3929 const data = await response.json(); 3930 departmentsCache[degreeLevel] = data.departments || []; 3931 return departmentsCache[degreeLevel]; 3932 } catch (error) { 3933 console.error('Bölümler yüklenemedi:', error); 3934 return []; 3935 } 3936 } 3937 3938 // Select'i doldur 3939 function populateSelect(selectEl, items, valueKey, textKey, placeholder) { 3940 selectEl.innerHTML = `<option value="">${placeholder}</option>`;
3941 items.forEach(item => { 3942 const opt = document.createElement('option'); 3943 opt.value = item[valueKey]; 3944 opt.textContent = item[textKey]; 3945 selectEl.appendChild(opt); 3946 }); 3947 refreshSelect2(selectEl); 3948 } 3949 3950 // ========== DanıÅman Tipi Seçimi (Emlak / SPK Lisanslı) ========== 3951 const consultantTypeInput = document.getElementById('consultant_type'); 3952 const consultantTypeEmlak = document.getElementById('consultant_type_emlak'); 3953 const consultantTypeSpk = document.getElementById('consultant_type_spk'); 3954 const consultantTypeLihkab = document.getElementById('consultant_type_lihkab'); 3955 const consultantLicenseWrapper = document.getElementById('consultant_license_wrapper'); 3956 const consultantLicenseInput = document.getElementById('consultant_license_no'); 3957 const consultantGraduationSection = document.getElementById('graduation-section-consultant'); 3958 3959 function shouldConsultantUseSpkFlow(type) { 3960 if (type === 'lihkab') return false; 3961 if (type === 'spk') return true; 3962 return !!(selectedCompanyProfile && selectedCompanyProfile.is_expert); 3963 } 3964 3965 function updateConsultantType(type) { 3966 if (!consultantTypeInput) return; 3967 consultantTypeInput.value = type; 3968 if (consultantTypeEmlak) consultantTypeEmlak.classList.toggle('active', type === 'emlak'); 3969 if (consultantTypeSpk) consultantTypeSpk.classList.toggle('active', type === 'spk'); 3970 if (consultantTypeLihkab) consultantTypeLihkab.classList.toggle('active', type === 'lihkab'); 3971 if (consultantLicenseWrapper) consultantLicenseWrapper.style.display = type === 'spk' ? 'block' : 'none'; 3972 if (consultantLicenseInput) { 3973 consultantLicenseInput.required = (type === 'spk') && !adminMode; 3974 consultantLicenseInput.value = type === 'spk' ? consultantLicenseInput.value : ''; 3975 } 3976 if (consultantGraduationSection) { 3977 consultantGraduationSection.style.display = adminMode ? 'none' : (type === 'lihkab' ? 'none' : 'block'); 3978 } 3979 const errLicense = document.getElementById('error-consultant_license_no_consultant'); 3980 if (errLicense && type !== 'spk') { errLicense.style.display = 'none'; errLicense.textContent = ''; } 3981 const isConsultantSpk = shouldConsultantUseSpkFlow(type); 3982 updateConsultantGraduationRequired(isConsultantSpk); 3983 } 3984 3985 if (consultantTypeEmlak) { 3986 consultantTypeEmlak.addEventListener('click', function() { updateConsultantType('emlak'); }); 3987 } 3988 if (consultantTypeSpk) { 3989 consultantTypeSpk.addEventListener('click', function() { updateConsultantType('spk'); }); 3990 } 3991 if (consultantTypeLihkab) { 3992 consultantTypeLihkab.addEventListener('click', function() { updateConsultantType('lihkab'); }); 3993 } 3994 window.updateConsultantType = updateConsultantType; 3995 const initialConsultantType = consultantTypeInput ? consultantTypeInput.value || 'emlak' : 'emlak'; 3996 updateConsultantType(initialConsultantType); 3997 3998 // Mezuniyet formu baÅlat (consultant veya corporate için) 3999 async function initGraduationForm(formType) { 4000 const educationLevelHidden = document.getElementById(`education_level_${formType}`); 4001 const universityIdHidden = document.getElementById(`university_id_${formType}`); 4002 const departmentIdHidden = document.getElementById(`department_id_${formType}`); 4003 const customDepartmentHidden = document.getElementById(`custom_department_${formType}`); 4004 const skipDiplomaHidden = document.getElementById(`skip_diploma_${formType}`); 4005 4006 const higherEducationFields = document.getElementById(`higher-education-fields-${formType}`); 4007 const universitySelect = document.getElementById(`university_select_${formType}`); 4008 const universityError = document.getElementById(`error-university_${formType}`); 4009 const departmentSelect = document.getElementById(`department_select_${formType}`); 4010 const customDepartmentInput = document.getElementById(`custom_department_input_${formType}`); 4011 const diplomaFileInput = document.getElementById(`diploma_file_${formType}`); 4012 const diplomaPreview = document.getElementById(`diploma_preview_${formType}`); 4013 const diplomaFilename = document.getElementById(`diploma_filename_${formType}`); 4014 const skipDiplomaCheckbox = document.getElementById(`skip_diploma_checkbox_${formType}`); 4015 4016 const radioButtons = document.querySelectorAll(`input[name="education_level_radio_${formType}"]`); 4017 const radioLabels = document.querySelectorAll(`#form-${formType} .education-level-option`); 4018 4019 if (!educationLevelHidden) return; 4020 4021 initSelect2(universitySelect, 'Ãniversite Seçiniz *');
4022 initSelect2(departmentSelect, 'Bölüm Seçiniz'); 4023 4024 // Radio button deÄiÅimi 4025 radioButtons.forEach(radio => { 4026 radio.addEventListener('change', async function() { 4027 const level = parseInt(this.value, 10); 4028 educationLevelHidden.value = level; 4029 4030 // Selected class güncelle 4031 radioLabels.forEach(label => { 4032 const labelLevel = parseInt(label.dataset.level, 10); 4033 if (labelLevel === level) { 4034 label.classList.add('selected'); 4035 } else { 4036 label.classList.remove('selected'); 4037 } 4038 }); 4039 4040 // Ãn Lisans (2) veya Lisans (1) seçilirse üniversite/bölüm alanlarını göster 4041 if (level === 1 || level === 2) { 4042 higherEducationFields.classList.add('visible'); 4043 clearUniversityError(universityError); 4044 universitySelect.disabled = true; 4045 populateSelect(universitySelect, [], 'id', 'name', 'Ãniversiteler yükleniyor...'); 4046 4047 // Ãniversiteleri yükle 4048 const universities = await loadUniversities(); 4049 populateSelect(universitySelect, universities, 'id', 'name', 'Ãniversite Seçiniz *'); 4050 universitySelect.disabled = universities.length === 0; 4051 4052 if (universities.length === 0) { 4053 const message = universitiesFetchError 4054 ? 'Ãniversite listesi yüklenemedi. Lütfen sayfayı yenileyin.' 4055 : 'Aktif üniversite bulunamadı. Lütfen daha sonra tekrar deneyin.'; 4056 showUniversityError(universityError, message); 4057 } else { 4058 clearUniversityError(universityError); 4059 } 4060 4061 // Bölümleri yükle (degree_level'e göre) 4062 const departments = await loadDepartments(level); 4063 populateSelect(departmentSelect, departments, 'id', 'name', 'Bölüm Seçiniz'); 4064 departmentSelect.disabled = false; 4065 } else { 4066 // OrtaöÄretim seçildi - alanları gizle ve temizle 4067 higherEducationFields.classList.remove('visible'); 4068 clearUniversityError(universityError); 4069 universityIdHidden.value = ''; 4070 departmentIdHidden.value = ''; 4071 customDepartmentHidden.value = ''; 4072 universitySelect.value = ''; 4073 departmentSelect.value = ''; 4074 customDepartmentInput.value = ''; 4075 universitySelect.disabled = false; 4076 departmentSelect.disabled = false; 4077 refreshSelect2(universitySelect); 4078 refreshSelect2(departmentSelect); 4079 } 4080 }); 4081 }); 4082 4083 // Label tıklaması da radio'yu tetiklesin
4084 radioLabels.forEach(label => { 4085 label.addEventListener('click', function() { 4086 const radio = this.querySelector('input[type="radio"]'); 4087 if (radio && !radio.checked) { 4088 radio.checked = true; 4089 radio.dispatchEvent(new Event('change')); 4090 } 4091 }); 4092 }); 4093 4094 // Ãniversite seçimi 4095 if (universitySelect) { 4096 universitySelect.addEventListener('change', function() { 4097 universityIdHidden.value = this.value; 4098 }); 4099 } 4100 4101 // Bölüm seçimi 4102 if (departmentSelect) { 4103 departmentSelect.addEventListener('change', function() { 4104 departmentIdHidden.value = this.value; 4105 // Bölüm seçilirse custom input'u temizle 4106 if (this.value) { 4107 customDepartmentInput.value = ''; 4108 customDepartmentHidden.value = ''; 4109 } 4110 }); 4111 } 4112 4113 // Custom bölüm giriÅi 4114 if (customDepartmentInput) { 4115 customDepartmentInput.addEventListener('input', function() { 4116 customDepartmentHidden.value = this.value; 4117 // Custom girilirse select'i temizle 4118 if (this.value.trim()) { 4119 departmentSelect.value = ''; 4120 departmentIdHidden.value = ''; 4121 } 4122 }); 4123 } 4124 4125 // Diploma dosya seçimi 4126 if (diplomaFileInput) { 4127 diplomaFileInput.addEventListener('change', function() { 4128 if (this.files && this.files[0]) { 4129 const file = this.files[0]; 4130 diplomaFilename.textContent = file.name; 4131 diplomaPreview.style.display = 'block'; 4132 4133 // Skip checkbox'ı temizle 4134 if (skipDiplomaCheckbox) { 4135 skipDiplomaCheckbox.checked = false; 4136 skipDiplomaHidden.value = ''; 4137 } 4138 } else { 4139 diplomaPreview.style.display = 'none'; 4140 } 4141 }); 4142 } 4143 4144 // Skip diploma checkbox 4145 if (skipDiplomaCheckbox) { 4146 skipDiplomaCheckbox.addEventListener('change', function() { 4147 skipDiplomaHidden.value = this.checked ? '1' : ''; 4148 }); 4149 } 4150 } 4151 4152 // Her iki form için mezuniyet formunu baÅlat 4153 initGraduationForm('consultant'); 4154 initGraduationForm('corporate'); 4155 4156 initRegisterAddress('consultant'); 4157 initRegisterAddress('corporate'); 4158 4159 // Sayfa yüklendiÄinde expert firma ise danıÅman mezuniyet zorunlu UI 4160 4161 4162 // Ãyelik tipi kartları / ?member_type= deep-link: tüm baÄımlılıklar hazır olduktan sonra 4163 initRegisterMemberTypeFlow(); 4164}); 4165</script>
4165 4166 4167 4168 <p class="pp-auth-panel__footer"> 4169 Zaten hesabınız var mı? 4170 <a href="/accounts/login/">GiriŠYapın</a> 4171 </p> 4172</div> 4173 4174 </div> 4175 </div> 4176 </div> 4177 </div> 4178 </div> 4179 </div> 4180 4181
4182<script id="auth-register-bootstrap" type="application/json">{"csrfToken": "hYcWwckumPqNrqKSgOPKQG5sTCzGzkXczfEdGiuOUTMOEaKMcn7spSCzV0Dt4nRU", "registerGooglePrefillUrl": "/accounts/register/google-prefill/", "registerGoogleClearUrl": "/accounts/register/google-clear/", "googleClientId": "", "googleAuthEnabled": false, "registerGoogle": null}</script>
4182 4183 4184
4185<script> 4186 /* Ãye tipi sekmesi: tam sayfa yenileme yok (fragment içi handler yedek) */ 4187 document.addEventListener('DOMContentLoaded', function () { 4188 document.querySelectorAll('.pp-auth-legacy-register .tab[data-tab]').forEach(function (tab) { 4189 if (tab.dataset.ppAuthTabBound) return; 4190 tab.dataset.ppAuthTabBound = '1'; 4191 tab.addEventListener('click', function (e) { 4192 e.preventDefault(); 4193 var t = tab.getAttribute('data-tab'); 4194 if (!t) return; 4195 try { 4196 var u = new URL(window.location.href); 4197 u.searchParams.set('member_type', t); 4198 window.history.replaceState({}, '', u.pathname + u.search); 4199 } catch (err) { /* ignore */ } 4200 var sc = document.querySelector('.pp-auth-portal__forms-scroll > .pp-auth-panel'); 4201 if (sc) sc.scrollTop = 0; 4202 }); 4203 }); 4204 }); 4205</script>
4205 4206 4207
4207<script type="module" src="/static/frontend/assets/authPortal-DhKHRlaw.js?v=1788697666221026500"></script>
4207 4208 4209</body> 4210</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.