1/** 2 * Kavya Global Network â Standalone Web Application & Visual Admin CMS Backend 3 */ 4 5(function () { 6 'use strict'; 7 8 let siteData = null; 9 try { 10 const cachedData = localStorage.getItem('kgn_site_data'); 11 if (cachedData) siteData = JSON.parse(cachedData); 12 } catch (e) {} 13 14 let formSubmissions = []; 15 let isAdminOpen = false; 16 let isCounselingOpen = false; 17 let isMockModalOpen = false; 18 let isMobileMenuOpen = false; 19 let activeAdminTab = 'hero'; 20 let formState = { name: '', email: '', phone: '', address: '', testType: 'PTE Academic', date: '', timeSlot: '08:00 AM - 11:00 AM' }; 21 let counselingState = { name: '', email: '', phone: '', country: 'USA', preferredDate: '', message: '' }; 22 let formStatus = null; 23 let counselingStatus = null; 24 let loginErrorMsg = ''; 25 let heroSlideIndex = 0; 26 let heroSlideTimer = null; 27 let partnerApps = []; 28 let verifiedPartner = null; 29 try { 30 const cachedPartner = localStorage.getItem('kgn_verified_partner'); 31 if (cachedPartner) verifiedPartner = JSON.parse(cachedPartner); 32 } catch (e) {} 33 34 function initHeroSlider() { 35 if (heroSlideTimer) clearInterval(heroSlideTimer); 36 37 // Warm-up subsequent slides shortly after initial render for instant 0ms transitions 38 setTimeout(() => { 39 const slides = document.querySelectorAll('.hero-carousel-slide'); 40 if (slides && slides.length > 1) { 41 slides.forEach((s, idx) => { 42 if (idx > 0) { 43 const img = s.querySelector('img'); 44 if (img && img.loading === 'lazy') { 45 img.loading = 'eager'; 46 } 47 } 48 }); 49 } 50 }, 1200); 51 52 heroSlideTimer = setInterval(() => { 53 const slides = document.querySelectorAll('.hero-carousel-slide'); 54 const dots = document.querySelectorAll('.hero-dot-indicator'); 55 if (!slides || slides.length === 0) return; 56 heroSlideIndex = (heroSlideIndex + 1) % slides.length; 57 slides.forEach((s, idx) => s.classList.toggle('active', idx === heroSlideIndex)); 58 dots.forEach((d, idx) => d.classList.toggle('active', idx === heroSlideIndex)); 59 }, 5000); 60 61 const track = document.getElementById('hero-carousel-track'); 62 if (track && !track._hasTouchListeners) { 63 track._hasTouchListeners = true; 64 let touchStartX = 0; 65 track.addEventListener('touchstart', (e) => { 66 if (e.touches && e.touches.length > 0) touchStartX = e.touches[0].clientX; 67 }, { passive: true }); 68 track.addEventListener('touchend', (e) => { 69 if (e.changedTouches && e.changedTouches.length > 0) { 70 const touchEndX = e.changedTouches[0].clientX; 71 const diff = touchStartX - touchEndX; 72 if (Math.abs(diff) > 40) { 73 if (diff > 0) window.KavyaChangeHeroSlide(1); 74 else window.KavyaChangeHeroSlide(-1); 75 } 76 } 77 }, { passive: true }); 78 } 79 } 80 81 window.KavyaChangeHeroSlide = function(direction) { 82 const slides = document.querySelectorAll('.hero-carousel-slide'); 83 const dots = document.querySelectorAll('.hero-dot-indicator'); 84 if (!slides || slides.length === 0) return; 85 heroSlideIndex = (heroSlideIndex + direction + slides.length) % slides.length; 86 slides.forEach((s, idx) => s.classList.toggle('active', idx === heroSlideIndex)); 87 dots.forEach((d, idx) => d.classList.toggle('active', idx === heroSlideIndex)); 88 initHeroSlider(); 89 }; 90 91 window.KavyaGoToHeroSlide = function(index) { 92 const slides = document.querySelectorAll('.hero-carousel-slide'); 93 const dots = document.querySelectorAll('.hero-dot-indicator'); 94 if (!slides || slides.length === 0) return; 95 heroSlideIndex = index; 96 slides.forEach((s, idx) => s.classList.toggle('active', idx === heroSlideIndex)); 97 dots.forEach((d, idx) => d.classList.toggle('active', idx === heroSlideIndex)); 98 initHeroSlider(); 99 }; 100 101 const API_BASE = '/api'; 102 103 async function loginAdmin(password) { 104 try { 105 const res = await fetch(`${API_BASE}/admin/login`, { 106 method: 'POST', 107 headers: { 'Content-Type': 'application/json' }, 108 body: JSON.stringify({ password }) 109 }); 110 const json = await res.json(); 111 if (json.success) { 112 sessionStorage.setItem('kgn_admin_authenticated', 'true'); 113 loginErrorMsg = ''; 114 isAdminOpen = true; 115 renderApp(); 116 } else { 117 loginErrorMsg = json.message || 'Incorrect password.'; 118 renderApp(); 119 } 120 } catch (err) { 121 loginErrorMsg = 'Network error verifying password.'; 122 renderApp(); 123 } 124 } 125 126 async function changeAdminPassword(currentPassword, newPassword) { 127 const msgDiv = document.getElementById('change-pass-msg'); 128 try { 129 const res = await fetch(`${API_BASE}/admin/change-password`, { 130 method: 'POST', 131 headers: { 'Content-Type': 'application/json' }, 132 body: JSON.stringify({ currentPassword, newPassword }) 133 }); 134 const json = await res.json(); 135 if (msgDiv) { 136 msgDiv.style.color = json.success ? '#28a745' : '#dc3545'; 137 msgDiv.innerHTML = (json.success ? '<i class="fa-solid fa-circle-check"></i> ' : '<i class="fa-solid fa-circle-exclamation"></i> ') + json.message; 138 } 139 } catch (err) { 140 if (msgDiv) { 141 msgDiv.style.color = '#dc3545'; 142 msgDiv.innerHTML = '<i class="fa-solid fa-circle-exclamation"></i> Error updating password.'; 143 } 144 } 145 } 146 147 async function loadData() { 148 try { 149 const res = await fetch(`${API_BASE}/site-data`); 150 const json = await res.json(); 151 if (json.success) { 152 siteData = json.data; 153 try { localStorage.setItem('kgn_site_data', JSON.stringify(json.data)); } catch (e) {} 154 renderApp(); 155 } 156 } catch (err) { 157 console.error('Failed to load site data:', err); 158 } 159 } 160 161 async function loadSubmissions() { 162 try { 163 const res = await fetch(`${API_BASE}/submissions`); 164 const json = await res.json(); 165 if (json.success) { 166 formSubmissions = json.data; 167 } 168 } catch (err) { 169 console.error('Failed to load submissions:', err); 170 } 171 } 172 173 async function loadPartnerApps() { 174 try { 175 const res = await fetch(`${API_BASE}/partner-apps`); 176 const json = await res.json(); 177 if (json.success) { 178 partnerApps = json.data || []; 179 } 180 } catch (err) { 181 console.error('Failed to load partner applications:', err); 182 } 183 } 184
185 let partnerSearchQuery = ''; 186 let partnerTypeFilter = 'all'; 187 let partnerStatusFilter = 'all'; 188 189 async function createPartnerApp(data) { 190 try { 191 const res = await fetch(`${API_BASE}/partner-apps`, { 192 method: 'POST', 193 headers: { 'Content-Type': 'application/json' }, 194 body: JSON.stringify(data) 195 }); 196 const json = await res.json(); 197 if (json.success) { 198 await loadPartnerApps(); 199 renderApp(); 200 return { success: true, partner: json.partner }; 201 } else { 202 return { success: false, message: json.message || 'Failed to create partner' }; 203 } 204 } catch (err) { 205 console.error('Failed to create partner app:', err); 206 return { success: false, message: 'Network error creating partner' }; 207 } 208 } 209 210 async function updatePartnerApp(id, data) { 211 try { 212 const res = await fetch(`${API_BASE}/partner-apps/${id}`, { 213 method: 'PATCH', 214 headers: { 'Content-Type': 'application/json' }, 215 body: JSON.stringify(data) 216 }); 217 const json = await res.json(); 218 if (json.success) { 219 await loadPartnerApps(); 220 renderApp(); 221 return { success: true, partner: json.partner }; 222 } else { 223 return { success: false, message: json.message || 'Failed to update partner' }; 224 } 225 } catch (err) { 226 console.error('Failed to update partner app:', err); 227 return { success: false, message: 'Network error updating partner' }; 228 } 229 } 230 231 async function updatePartnerAppStatus(id, status) { 232 try { 233 const res = await fetch(`${API_BASE}/partner-apps/${id}/status`, { 234 method: 'PATCH', 235 headers: { 'Content-Type': 'application/json' }, 236 body: JSON.stringify({ status }) 237 }); 238 const json = await res.json(); 239 if (json.success) { 240 await loadPartnerApps(); 241 renderApp(); 242 } else { 243 alert(json.message || 'Failed to update status'); 244 } 245 } catch (err) { 246 console.error('Failed to update partner app status:', err); 247 } 248 } 249 250 async function deletePartnerApp(id) { 251 if (!confirm('Are you sure you want to delete this partner application?')) return; 252 try { 253 const res = await fetch(`${API_BASE}/partner-apps/${id}`, { method: 'DELETE' }); 254 const json = await res.json(); 255 if (json.success) { 256 await loadPartnerApps(); 257 renderApp(); 258 } 259 } catch (err) { 260 console.error('Failed to delete partner application:', err); 261 } 262 } 263 264 function copyToClipboard(text, successMsg = 'Copied to clipboard!') { 265 navigator.clipboard.writeText(text).then(() => { 266 alert('ð ' + successMsg); 267 }).catch(() => { 268 const input = document.createElement('input'); 269 input.value = text; 270 document.body.appendChild(input); 271 input.select(); 272 document.execCommand('copy'); 273 document.body.removeChild(input); 274 alert('ð ' + successMsg); 275 }); 276 } 277 278 async function saveSiteData(updatedData) { 279 try { 280 const res = await fetch(`${API_BASE}/site-data`, { 281 method: 'POST', 282 headers: { 'Content-Type': 'application/json' }, 283 body: JSON.stringify(updatedData) 284 }); 285 const json = await res.json(); 286 if (json.success) { 287 siteData = json.data; 288 alert('â Site content saved successfully!'); 289 renderApp(); 290 } else { 291 alert('â Error saving site content.'); 292 } 293 } catch (err) { 294 console.error('Failed to save site data:', err); 295 alert('â Failed to connect to server.'); 296 } 297 } 298 299 let activeLeadFilter = 'all'; 300 301 async function deleteLead(id) { 302 if (!confirm('Are you sure you want to delete this lead submission?')) return; 303 try { 304 const res = await fetch(`${API_BASE}/submissions/${id}`, { method: 'DELETE' }); 305 const json = await res.json(); 306 if (json.success) { 307 await loadSubmissions(); 308 renderApp(); 309 } 310 } catch (err) { 311 console.error('Failed to delete lead:', err); 312 } 313 } 314 315 function validateEmail(email) { 316 if (!email || typeof email !== 'string') return false;
317 const re = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/; 318 return re.test(email.trim()); 319 } 320 321 function validatePhone(phone) { 322 if (!phone || typeof phone !== 'string') return false; 323 const digits = phone.replace(/[^0-9]/g, ''); 324 return digits.length >= 7 && digits.length <= 15; 325 } 326 327 async function submitForm(e) { 328 if (e && e.preventDefault) e.preventDefault(); 329 if (!formState.name || !formState.name.trim()) { 330 formStatus = { type: 'error', text: 'Please enter your full name.' }; 331 renderApp(); 332 return; 333 } 334 335 if (!formState.email || !validateEmail(formState.email)) { 336 formStatus = { type: 'error', text: 'Please enter a valid email address (e.g. [email protected]).' }; 337 renderApp(); 338 return; 339 } 340 341 if (!formState.phone || !validatePhone(formState.phone)) { 342 formStatus = { type: 'error', text: 'Please enter a valid phone or WhatsApp number (minimum 7 digits).' }; 343 renderApp(); 344 return; 345 } 346 347 try { 348 const payload = { 349 source: 'Mock Test Registration', 350 category: formState.testType || 'PTE Academic', 351 name: formState.name.trim(), 352 email: formState.email.trim(), 353 phone: formState.phone.trim(), 354 address: formState.address || '', 355 testType: formState.testType, 356 timeSlot: formState.timeSlot, 357 date: formState.date || '' 358 }; 359 360 const res = await fetch(`${API_BASE}/submit-form`, { 361 method: 'POST', 362 headers: { 'Content-Type': 'application/json' }, 363 body: JSON.stringify(payload) 364 }); 365 const json = await res.json(); 366 if (json.success) { 367 formStatus = { type: 'success', text: json.message }; 368 formState = { name: '', email: '', phone: '', address: '', testType: 'PTE Academic', date: '', timeSlot: '08:00 AM - 11:00 AM' }; 369 loadSubmissions(); 370 } else { 371 formStatus = { type: 'error', text: json.message }; 372 } 373 } catch (err) { 374 formStatus = { type: 'error', text: 'Network error. Please try again.' }; 375 } 376 renderApp(); 377 } 378 379 async function submitCounselingForm(e) { 380 e.preventDefault(); 381 if (!counselingState.name || !counselingState.name.trim()) { 382 counselingStatus = { type: 'error', text: 'Please enter your full name.' }; 383 renderApp(); 384 return; 385 } 386 387 if (!counselingState.email || !validateEmail(counselingState.email)) { 388 counselingStatus = { type: 'error', text: 'Please enter a valid email address (e.g. [email protected]).' }; 389 renderApp(); 390 return; 391 } 392 393 if (!counselingState.phone || !validatePhone(counselingState.phone)) { 394 counselingStatus = { type: 'error', text: 'Please enter a valid phone or WhatsApp number (minimum 7 digits).' }; 395 renderApp(); 396 return; 397 } 398 399 const sessionType = counselingState.sessionType || 'whatsapp-video'; 400 const sessionLabel = sessionType === 'whatsapp-video' ? 'WhatsApp Video Call' 401 : sessionType === 'in-person' ? 'In-Person (Kathmandu Office)' 402 : 'Phone Call'; 403 404 try { 405 const payload = { 406 source: `Online Counseling Booking â ${sessionLabel}`, 407 category: `Study in ${counselingState.country}`, 408 name: counselingState.name.trim(), 409 email: counselingState.email.trim(), 410 phone: counselingState.phone.trim(), 411 country: counselingState.country, 412 date: counselingState.preferredDate || 'Flexible', 413 notes: counselingState.message || '', 414 address: `${sessionLabel} | ${counselingState.country}` 415 }; 416 417 const res = await fetch(`${API_BASE}/submit-form`, { 418 method: 'POST', 419 headers: { 'Content-Type': 'application/json' }, 420 body: JSON.stringify(payload) 421 }); 422 const json = await res.json(); 423 if (json.success) { 424 const successMsg = sessionType === 'whatsapp-video' 425 ? 'ð Booked! Our counselor will send you a WhatsApp Video Call at your preferred time. Check your WhatsApp!' 426 : sessionType === 'in-person' 427 ? 'ð Appointment confirmed! Visit our New Baneshwor office. We\'ll confirm the time via WhatsApp/Email.' 428 : 'ð Confirmed! Our counselor will call you shortly. Please keep your phone available.'; 429 counselingStatus = { type: 'success', text: successMsg }; 430 counselingState = { name: '', email: '', phone: '', country: 'USA', preferredDate: '', message: '', sessionType: 'whatsapp-video' }; 431 loadSubmissions(); 432 } else { 433 counselingStatus = { type: 'error', text: json.message }; 434 } 435 } catch (err) { 436 counselingStatus = { type: 'error', text: 'Network error. Please try again.' }; 437 } 438 renderApp(); 439 } 440 441 442 // Global Handlers for Sub-Page Inquiries & Forms 443 window.KavyaHandleQuickInquiry = async function (form, destinationName) { 444 const statusDiv = form.querySelector('.quick-inquiry-status'); 445 const submitBtn = form.querySelector('button[type="submit"]'); 446 const origText = submitBtn ? submitBtn.innerHTML : ''; 447 if (submitBtn) { 448 submitBtn.disabled = true; 449 submitBtn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Submitting...'; 450 } 451 452 const formData = new FormData(form); 453 const nameVal = (formData.get('name') || '').trim(); 454 const phoneVal = (formData.get('phone') || '').trim(); 455 const emailVal = (formData.get('email') || '').trim(); 456 457 if (!nameVal) { 458 if (statusDiv) { 459 statusDiv.style.display = 'block'; 460 statusDiv.style.color = '#dc3545'; 461 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Please enter your full name.'; 462 } 463 if (submitBtn) { 464 submitBtn.disabled = false;
465 submitBtn.innerHTML = origText; 466 } 467 return; 468 } 469 470 if (!emailVal || !validateEmail(emailVal)) { 471 if (statusDiv) { 472 statusDiv.style.display = 'block'; 473 statusDiv.style.color = '#dc3545'; 474 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Please enter a valid email address (e.g. [email protected]).'; 475 } 476 if (submitBtn) { 477 submitBtn.disabled = false; 478 submitBtn.innerHTML = origText; 479 } 480 return; 481 } 482 483 if (!phoneVal || !validatePhone(phoneVal)) { 484 if (statusDiv) { 485 statusDiv.style.display = 'block'; 486 statusDiv.style.color = '#dc3545'; 487 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Please enter a valid phone or WhatsApp number (7â15 digits).'; 488 } 489 if (submitBtn) { 490 submitBtn.disabled = false; 491 submitBtn.innerHTML = origText; 492 } 493 return; 494 } 495 496 const payload = { 497 source: `Sidebar Quick Inquiry (${destinationName})`, 498 category: `Study in ${destinationName}`, 499 name: nameVal, 500 phone: phoneVal, 501 email: emailVal, 502 address: `Qualification: ${formData.get('qualification') || 'N/A'} | English Test: ${formData.get('testScore') || 'N/A'}`, 503 notes: `Target Destination: ${destinationName}` 504 }; 505 506 try { 507 const res = await fetch(`${API_BASE}/submit-form`, { 508 method: 'POST', 509 headers: { 'Content-Type': 'application/json' }, 510 body: JSON.stringify(payload) 511 }); 512 const json = await res.json(); 513 if (statusDiv) { 514 statusDiv.style.display = 'block'; 515 statusDiv.style.color = json.success ? '#28a745' : '#dc3545'; 516 statusDiv.innerHTML = json.success 517 ? '<i class="fa-solid fa-circle-check"></i> Inquiry received! Our counselor will contact you via WhatsApp shortly.' 518 : `<i class="fa-solid fa-triangle-exclamation"></i> ${json.message}`; 519 } 520 if (json.success) { 521 form.reset(); 522 loadSubmissions(); 523 } 524 } catch (err) { 525 if (statusDiv) { 526 statusDiv.style.display = 'block'; 527 statusDiv.style.color = '#dc3545'; 528 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Network error. Please try again.'; 529 } 530 } finally { 531 if (submitBtn) { 532 submitBtn.disabled = false; 533 submitBtn.innerHTML = origText; 534 } 535 } 536 }; 537 538 window.KavyaSubmitMockTest = async function (form) { 539 const formData = new FormData(form); 540 formState = { 541 name: formData.get('name'), 542 phone: formData.get('phone'), 543 email: formData.get('email'), 544 address: formData.get('address') || '', 545 testType: formData.get('testType') || 'PTE Academic', 546 timeSlot: formData.get('timeSlot') || '08:00 AM - 11:00 AM', 547 date: formData.get('date') || '' 548 }; 549 await submitForm(); 550 }; 551 552 window.KavyaSubmitContact = async function (form) { 553 const formData = new FormData(form); 554 counselingState = { 555 name: formData.get('name'), 556 email: formData.get('email'), 557 phone: formData.get('phone'), 558 country: formData.get('country') || 'Australia', 559 preferredDate: formData.get('preferredDate') || 'In-Person (Kathmandu Office)', 560 message: formData.get('message') || '' 561 }; 562 await submitCounselingForm({ preventDefault: () => {} }); 563 }; 564 565 window.KavyaSubmitPartnership = async function (form) { 566 const statusDiv = document.getElementById('partner-form-status') || form.querySelector('.partner-form-status'); 567 const submitBtn = form.querySelector('button[type="submit"]'); 568 const origText = submitBtn ? submitBtn.innerHTML : ''; 569 if (submitBtn) { 570 submitBtn.disabled = true; 571 submitBtn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Submitting Application...'; 572 } 573 574 const formData = new FormData(form); 575 const partnerType = formData.get('partnerType') || 'Corporate Partner'; 576 const nameVal = (formData.get('name') || '').trim(); 577 const emailVal = (formData.get('email') || '').trim(); 578 const phoneVal = (formData.get('phone') || '').trim(); 579 const orgName = formData.get('organization') || 'N/A'; 580 const website = formData.get('website') || 'N/A'; 581 const location = formData.get('location') || 'N/A'; 582 const proposalMsg = formData.get('message') || ''; 583 584 if (!nameVal) { 585 if (statusDiv) { 586 statusDiv.style.display = 'block'; 587 statusDiv.style.background = '#f8d7da'; 588 statusDiv.style.color = '#721c24'; 589 statusDiv.style.borderLeft = '4px solid #dc3545'; 590 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Please enter your contact person name.'; 591 } 592 if (submitBtn) { 593 submitBtn.disabled = false;
594 submitBtn.innerHTML = origText; 595 } 596 return; 597 } 598 599 if (!emailVal || !validateEmail(emailVal)) { 600 if (statusDiv) { 601 statusDiv.style.display = 'block'; 602 statusDiv.style.background = '#f8d7da'; 603 statusDiv.style.color = '#721c24'; 604 statusDiv.style.borderLeft = '4px solid #dc3545'; 605 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Please enter a valid corporate email address.'; 606 } 607 if (submitBtn) { 608 submitBtn.disabled = false; 609 submitBtn.innerHTML = origText; 610 } 611 return; 612 } 613 614 if (!phoneVal || !validatePhone(phoneVal)) { 615 if (statusDiv) { 616 statusDiv.style.display = 'block'; 617 statusDiv.style.background = '#f8d7da'; 618 statusDiv.style.color = '#721c24'; 619 statusDiv.style.borderLeft = '4px solid #dc3545'; 620 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Please enter a valid phone or WhatsApp number (7â15 digits).'; 621 } 622 if (submitBtn) { 623 submitBtn.disabled = false; 624 submitBtn.innerHTML = origText; 625 } 626 return; 627 } 628 629 const payload = { 630 source: `Partner with Us Application (${partnerType})`, 631 category: `B2B Partnership: ${partnerType}`, 632 name: nameVal, 633 email: emailVal, 634 phone: phoneVal, 635 address: `Organization: ${orgName} | Location: ${location} | Web: ${website}`, 636 notes: proposalMsg 637 }; 638 639 try { 640 const res = await fetch(`${API_BASE}/submit-form`, { 641 method: 'POST', 642 headers: { 'Content-Type': 'application/json' }, 643 body: JSON.stringify(payload) 644 }); 645 const json = await res.json(); 646 if (statusDiv) { 647 statusDiv.style.display = 'block'; 648 if (json.success) { 649 statusDiv.style.background = '#d4edda'; 650 statusDiv.style.color = '#155724'; 651 statusDiv.style.borderLeft = '4px solid #28a745'; 652 statusDiv.innerHTML = '<i class="fa-solid fa-circle-check"></i> Thank you! Your partnership application has been received. Our Corporate Relations team will review your proposal and respond to your official email within 24 business hours.'; 653 form.reset(); 654 loadSubmissions(); 655 } else { 656 statusDiv.style.background = '#f8d7da'; 657 statusDiv.style.color = '#721c24'; 658 statusDiv.style.borderLeft = '4px solid #dc3545'; 659 statusDiv.innerHTML = `<i class="fa-solid fa-triangle-exclamation"></i> ${json.message || 'Submission failed. Please try again.'}`; 660 } 661 } 662 } catch (err) { 663 if (statusDiv) { 664 statusDiv.style.display = 'block'; 665 statusDiv.style.background = '#f8d7da'; 666 statusDiv.style.color = '#721c24'; 667 statusDiv.style.borderLeft = '4px solid #dc3545'; 668 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Network error. Please email us directly at [email protected]'; 669 } 670 } finally { 671 if (submitBtn) { 672 submitBtn.disabled = false; 673 submitBtn.innerHTML = origText; 674 } 675 } 676 }; 677 678 window.KavyaSubmitPartnerApp = async function (form, partnerType) { 679 const statusDivId = partnerType === 'education-provider' ? 'edu-provider-form-status' : 'sub-agent-form-status'; 680 const statusDiv = document.getElementById(statusDivId) || form.querySelector('.form-status'); 681 const submitBtn = form.querySelector('button[type="submit"]'); 682 const origText = submitBtn ? submitBtn.innerHTML : ''; 683 if (submitBtn) { 684 submitBtn.disabled = true; 685 submitBtn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Submitting Application...'; 686 } 687 688 const formData = new FormData(form); 689 const nameVal = (formData.get('name') || '').trim(); 690 const emailVal = (formData.get('email') || '').trim(); 691 const phoneVal = (formData.get('phone') || '').trim(); 692 693 if (!nameVal) { 694 if (statusDiv) { 695 statusDiv.style.display = 'block'; 696 statusDiv.style.background = '#f8d7da'; 697 statusDiv.style.color = '#721c24'; 698 statusDiv.style.borderLeft = '4px solid #dc3545'; 699 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Please enter your contact person name.'; 700 } 701 if (submitBtn) { 702 submitBtn.disabled = false;
703 submitBtn.innerHTML = origText; 704 } 705 return; 706 } 707 708 if (!emailVal || !validateEmail(emailVal)) { 709 if (statusDiv) { 710 statusDiv.style.display = 'block'; 711 statusDiv.style.background = '#f8d7da'; 712 statusDiv.style.color = '#721c24'; 713 statusDiv.style.borderLeft = '4px solid #dc3545'; 714 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Please enter a valid corporate/official email address.'; 715 } 716 if (submitBtn) { 717 submitBtn.disabled = false; 718 submitBtn.innerHTML = origText; 719 } 720 return; 721 } 722 723 if (!phoneVal || !validatePhone(phoneVal)) { 724 if (statusDiv) { 725 statusDiv.style.display = 'block'; 726 statusDiv.style.background = '#f8d7da'; 727 statusDiv.style.color = '#721c24'; 728 statusDiv.style.borderLeft = '4px solid #dc3545'; 729 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Please enter a valid phone or WhatsApp number (7â15 digits).'; 730 } 731 if (submitBtn) { 732 submitBtn.disabled = false; 733 submitBtn.innerHTML = origText; 734 } 735 return; 736 } 737 738 const selectedCountries = []; 739 form.querySelectorAll('input[name="countries"]:checked').forEach(cb => selectedCountries.push(cb.value)); 740 741 const payload = { 742 partnerType: partnerType || 'sub-agent', 743 name: nameVal, 744 email: emailVal, 745 phone: phoneVal, 746 company: formData.get('company'), 747 location: formData.get('location'), 748 website: formData.get('website'), 749 license: formData.get('license'), 750 studentVolume: formData.get('studentVolume'), 751 programs: formData.get('programs'), 752 commission: formData.get('commission'), 753 countries: selectedCountries, 754 message: formData.get('message') 755 }; 756 757 try { 758 const res = await fetch(`${API_BASE}/partner-apply`, { 759 method: 'POST', 760 headers: { 'Content-Type': 'application/json' }, 761 body: JSON.stringify(payload) 762 }); 763 const json = await res.json(); 764 if (statusDiv) { 765 statusDiv.style.display = 'block'; 766 if (json.success) { 767 statusDiv.style.background = '#d4edda'; 768 statusDiv.style.color = '#155724'; 769 statusDiv.style.borderLeft = '4px solid #28a745'; 770 statusDiv.innerHTML = `<i class="fa-solid fa-circle-check"></i> ${json.message || 'Thank you! Your application has been submitted successfully.'}`; 771 form.reset(); 772 loadPartnerApps(); 773 } else { 774 statusDiv.style.background = '#f8d7da'; 775 statusDiv.style.color = '#721c24'; 776 statusDiv.style.borderLeft = '4px solid #dc3545'; 777 statusDiv.innerHTML = `<i class="fa-solid fa-triangle-exclamation"></i> ${json.message || 'Submission failed. Please try again.'}`; 778 } 779 } 780 } catch (err) { 781 if (statusDiv) { 782 statusDiv.style.display = 'block'; 783 statusDiv.style.background = '#f8d7da'; 784 statusDiv.style.color = '#721c24'; 785 statusDiv.style.borderLeft = '4px solid #dc3545'; 786 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Network error. Please email us directly at [email protected]'; 787 } 788 } finally { 789 if (submitBtn) { 790 submitBtn.disabled = false; 791 submitBtn.innerHTML = origText; 792 } 793 } 794 }; 795 796 window.openPartnerModal = function(type) { 797 let modal = document.getElementById('b2b-partner-modal'); 798 if (!modal) { 799 modal = document.createElement('div'); 800 modal.id = 'b2b-partner-modal'; 801 modal.className = 'lightbox-overlay'; 802 modal.onclick = function(e) { 803 if (e.target === modal) window.closePartnerModal(); 804 }; 805 document.body.appendChild(modal); 806 } 807 808 const isEdu = type === 'education-provider'; 809 const modalTitle = isEdu ? 'Education Provider Application' : 'Regional Partner & Sub-Agent Registration'; 810 const modalSubtitle = isEdu 811 ? 'Universities, colleges, and pathway institutions seeking direct representation in Nepal.' 812 : 'Regional consultancies and agencies across Nepal seeking access to our 60+ university network.'; 813 const modalIcon = isEdu ? 'fa-building-columns' : 'fa-handshake'; 814 815 const formHtml = isEdu ? ` 816 <form id="edu-provider-apply-modal-form" onsubmit="event.preventDefault();
816 window.KavyaSubmitPartnerApp(this, 'education-provider');"> 817 <div class="b2b-modal-form-grid"> 818 <div class="form-group-pro" style="margin: 0;"> 819 <label>Contact Person Name *</label> 820 <input type="text" name="name" placeholder="Full name" required /> 821 </div> 822 <div class="form-group-pro" style="margin: 0;"> 823 <label>Official Email Address *</label> 824 <input type="email" name="email" placeholder="[email protected]" required /> 825 </div> 826 <div class="form-group-pro" style="margin: 0;"> 827 <label>Phone / WhatsApp *</label> 828 <input type="tel" name="phone" placeholder="+1 / +44 / +61 ..." required /> 829 </div> 830 <div class="form-group-pro" style="margin: 0;"> 831 <label>Institution Name *</label> 832 <input type="text" name="company" placeholder="University or College name" required /> 833 </div> 834 <div class="form-group-pro" style="margin: 0;"> 835 <label>Country & City *</label> 836 <input type="text" name="location" placeholder="e.g. Sydney, Australia" required /> 837 </div> 838 <div class="form-group-pro" style="margin: 0;"> 839 <label>Institution Website</label> 840 <input type="url" name="website" placeholder="https://www.institution.edu" /> 841 </div> 842 </div> 843 <div class="form-group-pro" style="margin: 14px 0 0;"> 844 <label>Programs & Primary Intakes</label> 845 <input type="text" name="programs" placeholder="e.g. Undergraduate & Postgraduate â Spring, Fall" /> 846 </div> 847 <div class="form-group-pro" style="margin: 14px 0 0;"> 848 <label>Collaboration Scope / Proposed Terms</label> 849 <select name="commission"> 850 <option value="">Select collaboration model</option> 851 <option value="Direct University Representation MOU">Direct University Representation MOU</option> 852 <option value="Pathway / Foundation Provider Agreement">Pathway / Foundation Provider Agreement</option> 853 <option value="In-Country Spot Admissions & Recruitment">In-Country Spot Admissions & Recruitment</option> 854 <option value="Institutional Exchange & Articulation">Institutional Exchange & Articulation</option> 855 <option value="Other Formal Partnership">Other Formal Partnership</option> 856 </select> 857 </div> 858 <div class="form-group-pro" style="margin: 14px 0 0;"> 859 <label>Institutional Message / Objectives</label> 860 <textarea name="message" rows="3" placeholder="Share your institution's profile, scholarship offerings, or recruitment targets..."></textarea> 861 </div> 862 <div id="edu-provider-form-status" style="display:none; padding:12px 16px; border-radius:8px; font-size:13px; margin-top:14px; font-weight:600;"></div> 863 <button type="submit" class="btn-submit-partner-form" style="margin-top: 18px; width: 100%;"> 864 <i class="fa-solid fa-paper-plane"></i> Submit Institutional Inquiry 865 </button> 866 <p style="text-align:center; margin: 10px 0 0; font-size: 11.5px; color: #889b94;"><i class="fa-solid fa-shield-halved"></i> Strictly confidential B2B communication. Reviewed within 2 to 3 business days.</p> 867 </form> 868 ` : ` 869 <form id="sub-agent-apply-modal-form" onsubmit="event.preventDefault(); window.KavyaSubmitPartnerApp(this, 'sub-agent');"> 870 <div class="b2b-modal-form-grid"> 871 <div class="form-group-pro" style="margin: 0;"> 872 <label>Contact Person Name *</label> 873 <input type="text" name="name" placeholder="Your full name" required /> 874 </div> 875 <div class="form-group-pro" style="margin: 0;"> 876 <label>Email Address *</label> 877 <input type="email" name="email" placeholder="[email protected]" required /> 878 </div> 879 <div class="form-group-pro" style="margin: 0;"> 880 <label>WhatsApp / Phone *</label> 881 <input type="tel" name="phone" placeholder="+977 9XXXXXXXX" required /> 882 </div> 883 <div class="form-group-pro" style="margin: 0;"> 884 <label>Company / Agency Name *</label> 885 <input type="text" name="company" placeholder="Your consultancy
885name" required /> 886 </div> 887 <div class="form-group-pro" style="margin: 0;"> 888 <label>City / District *</label> 889 <input type="text" name="location" placeholder="e.g. Pokhara, Gandaki" required /> 890 </div> 891 <div class="form-group-pro" style="margin: 0;"> 892 <label>MoSD License / Reg. No.</label> 893 <input type="text" name="license" placeholder="MoSD or Company Reg. Number" /> 894 </div> 895 </div> 896 <div class="form-group-pro" style="margin: 14px 0 0;"> 897 <label>Approximate Student Referrals per Year *</label> 898 <select name="studentVolume" required> 899 <option value="">Select estimated annual volume</option> 900 <option value="1â5 students/year">1â5 students per year</option> 901 <option value="5â15 students/year">5â15 students per year</option> 902 <option value="15â30 students/year">15â30 students per year</option> 903 <option value="30+ students/year">30+ students per year</option> 904 </select> 905 </div> 906 <div class="form-group-pro" style="margin: 14px 0 0;"> 907 <label>Target Study Destinations (select all that apply)</label> 908 <div class="b2b-modal-dest-grid"> 909 ${['Australia', 'USA', 'United Kingdom', 'Canada', 'Germany', 'Japan', 'Korea', 'Other'].map(c => ` 910 <label style="display:flex; align-items:center; gap:8px; font-size:12.5px; font-weight:600; color:#334; cursor:pointer; background:#f8faf9; padding:6px 10px; border-radius:6px; border: 1px solid #dde9e6;"> 911 <input type="checkbox" name="countries" value="${c}" style="width:15px; height:15px; cursor:pointer;" /> 912 ${c} 913 </label> 914 `).join('')} 915 </div> 916 </div> 917 <div class="form-group-pro" style="margin: 14px 0 0;"> 918 <label>Additional Information</label> 919 <textarea name="message" rows="3" placeholder="Tell us about your organization's history, local market presence, or collaboration interests..."></textarea> 920 </div> 921 <div id="sub-agent-form-status" style="display:none; padding:12px 16px; border-radius:8px; font-size:13px; margin-top:14px; font-weight:600;"></div> 922 <button type="submit" class="btn-submit-partner-form" style="margin-top: 18px; width: 100%; background: linear-gradient(135deg, #1a1a2e, #0f3460);"> 923 <i class="fa-solid fa-handshake"></i> Submit Regional Partner Application 924 </button> 925 <p style="text-align:center; margin: 10px 0 0; font-size: 11.5px; color: #889b94;"><i class="fa-solid fa-shield-halved"></i> Strictly confidential. Protected under Kavya Global Privacy Standards.</p> 926 </form> 927 `; 928 929 modal.innerHTML = ` 930 <div class="lightbox-container" style="max-width: 680px; width: 94vw; max-height: 92vh; display: flex; flex-direction: column; background: #ffffff; border-radius: 16px; overflow: hidden; box-shadow: 0 25px 70px rgba(0,0,0,0.35);"> 931 <div style="background: linear-gradient(135deg, #004a3e 0%, #002c25 100%); color: #ffffff; padding: 18px 24px; display: flex; justify-content: space-between; align-items: center;"> 932 <div style="display: flex; align-items: center; gap: 12px;"> 933 <div style="width: 40px; height: 40px; background: rgba(255,255,255,0.15); border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 18px; color: #fc9b09;"> 934 <i class="fa-solid ${modalIcon}"></i> 935 </div> 936 <div> 937 <h3 style="margin: 0; font-size: 17px; font-weight: 800; color: #ffffff;">${modalTitle}</h3> 938 <p style="margin: 2px 0 0; font-size: 12px; color: rgba(255,255,255,0.75);">${modalSubtitle}</p> 939 </div> 940 </div> 941 <button onclick="window.closePartnerModal()" style="color: #ffffff; background: transparent; border: none; font-size: 24px; cursor: pointer; padding: 4px 8px; line-height: 1;">×</button> 942 </div> 943 <div style="padding: 24px; overflow-y: auto; flex: 1; background: #fafcfb;"> 944 ${formHtml} 945 </div> 946 </div> 947 `; 948 949 modal.classList.add('active'); 950 }; 951 952 window.closePartnerModal = function() { 953 const modal = document.getElementById('b2b-partner-modal'); 954 if (modal) modal.classList.remove('active'); 955 }; 956 957 window.openDispatchModal = function() {
958 let modal = document.getElementById('b2b-dispatch-modal'); 959 if (!modal) { 960 modal = document.createElement('div'); 961 modal.id = 'b2b-dispatch-modal'; 962 modal.className = 'lightbox-overlay'; 963 modal.onclick = function(e) { 964 if (e.target === modal) window.closeDispatchModal(); 965 }; 966 document.body.appendChild(modal); 967 } 968 969 const isVerified = Boolean(verifiedPartner); 970 971 const bodyHtml = !isVerified ? ` 972 <!-- Partner Login Gate --> 973 <div style="max-width: 540px; margin: 10px auto; background: #ffffff; border: 1px solid #c8e0da; border-radius: 16px; padding: 36px 30px; box-shadow: 0 8px 30px rgba(0,74,62,0.06); text-align: center;"> 974 <div style="width: 60px; height: 60px; background: linear-gradient(135deg, #004a3e, #006051); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 16px; color: #fff; font-size: 22px; box-shadow: 0 6px 18px rgba(0,74,62,0.25);"> 975 <i class="fa-solid fa-shield-halved"></i> 976 </div> 977 <h3 style="margin: 0 0 8px; font-size: 20px; font-weight: 800; color: #00332a;">Partner Access Verification</h3> 978 <p style="margin: 0 0 20px; font-size: 13px; color: #556; line-height: 1.6;">Please enter your <strong>Unique Partner ID</strong> (e.g. <code>KGN-SA-XXXX</code> or <code>KGN-EDU-XXXX</code>) issued by Kavya Global Network to unlock direct document dispatch.</p> 979 980 <form onsubmit="event.preventDefault(); window.KavyaLoginPartner(this);" style="text-align: left;"> 981 <div class="form-group-pro" style="margin-bottom: 16px;"> 982 <label style="font-weight: 700; color: #00332a; font-size: 13px;">Unique Partner ID *</label> 983 <div style="position: relative;"> 984 <input type="text" id="b2b-partner-id-input" placeholder="e.g. KGN-SA-1024" required style="text-transform: uppercase; font-weight: 800; letter-spacing: 1px; padding-left: 42px; font-size: 14.5px; width: 100%;" /> 985 <i class="fa-solid fa-id-badge" style="position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: #004a3e; font-size: 16px;"></i> 986 </div> 987 </div> 988 989 <div id="b2b-login-status" style="display:none; padding:12px 16px; border-radius:8px; font-size:13px; margin-bottom:16px; font-weight:600;"></div> 990 991 <button type="submit" class="btn-submit-partner-form" style="width: 100%; padding: 13px 20px; font-size: 14px; display: flex; align-items: center; justify-content: center; gap: 8px;"> 992 <i class="fa-solid fa-key"></i> Unlock Document Portal 993 </button> 994 995 <div style="margin-top: 18px; padding-top: 16px; border-top: 1px dashed #d5e2df; text-align: center; font-size: 12px; color: #667;"> 996 <p style="margin: 0 0 6px;">Don't have a Partner ID yet?</p> 997 <a href="#register" onclick="window.closeDispatchModal(); window.openPartnerModal('sub-agent'); return false;" style="color: #004a3e; font-weight: 800; text-decoration: underline; margin-right: 12px;">Apply as Regional Partner</a> 998 <span style="color: #ccc;">â¢</span> 999 <a href="#register" onclick="window.closeDispatchModal(); window.openPartnerModal('education-provider'); return false;" style="color: #004a3e; font-weight: 800; text-decoration: underline; margin-left: 12px;">Apply as Institution</a> 1000 </div> 1001 </form> 1002 </div> 1003 ` : ` 1004 <!-- Partner Authenticated Header Strip --> 1005 <div style="background: #e8f5f1; border: 1px solid #b8e2d6; border-radius: 12px; padding: 14px 18px; margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px;"> 1006 <div style="display: flex; align-items: center; gap: 12px;"> 1007 <div style="width: 40px; height: 40px; background: #004a3e; color: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 16px;"> 1008 <i class="fa-solid fa-circle-check"></i> 1009 </div> 1010 <div> 1011 <div style="font-weight: 800; color: #00332a; font-size: 14.5px;"> 1012 Verified Partner: ${verifiedPartner.company || verifiedPartner.name} 1013 </div> 1014 <div style="font-size: 12px; color: #006051; margin-top: 2px;"> 1015 ID: <strong>${verifiedPartner.partnerCode || verifiedPartner.id}</strong> • Contact: ${verifiedPartner.email} •
1015 <span style="text-transform: capitalize;">${verifiedPartner.partnerType || 'Partner'}</span> 1016 </div> 1017 </div> 1018 </div> 1019 <button onclick="window.KavyaLogoutPartner()" style="background: #ffffff; color: #dc2626; border: 1px solid #fecaca; padding: 6px 14px; border-radius: 20px; font-size: 12px; font-weight: 700; cursor: pointer; display: flex; align-items: center; gap: 6px;"> 1020 <i class="fa-solid fa-arrow-right-from-bracket"></i> Switch / Exit Partner 1021 </button> 1022 </div> 1023 1024 <!-- Unlocked Document Dispatch Workspace --> 1025 <div class="b2b-dispatch-grid"> 1026 <!-- Upload Zone --> 1027 <div class="b2b-upload-col"> 1028 <div class="b2b-dropzone" id="b2b-dropzone" onclick="document.getElementById('b2b-file-input').click();"> 1029 <div class="b2b-dropzone-inner"> 1030 <div class="b2b-drop-icon"><i class="fa-solid fa-cloud-arrow-up"></i></div> 1031 <h4>Drag & Drop Documents Here</h4> 1032 <p>or <strong>click to browse</strong> from your device</p> 1033 <div class="b2b-format-pills"> 1034 <span>PDF</span><span>DOC</span><span>DOCX</span><span>JPG</span><span>PNG</span><span>XLS</span><span>ZIP</span> 1035 </div> 1036 <div class="b2b-limit-notice"><i class="fa-solid fa-circle-info"></i> Max 15MB per file • 25MB total</div> 1037 </div> 1038 </div> 1039 <input type="file" id="b2b-file-input" multiple accept=".pdf,.doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png,.webp,.zip,.rar" style="display:none;" onchange="window.handleB2bFilesSelected(this.files)" /> 1040 <div id="b2b-review-container" style="margin-top: 14px;"></div> 1041 </div> 1042 1043 <!-- Sender Info & Send --> 1044 <div class="b2b-sender-col"> 1045 <form id="b2b-file-dispatch-form" onsubmit="event.preventDefault(); window.KavyaSubmitB2bFiles(this);"> 1046 <h4 class="b2b-sender-title"><i class="fa-solid fa-user-tie"></i> Verified Partner Submission</h4> 1047 <div class="b2b-form-row"> 1048 <div class="b2b-form-group"> 1049 <label>Contact Person Name *</label> 1050 <input type="text" id="b2b-sender-name" value="${verifiedPartner.name || ''}" placeholder="Contact person name" required /> 1051 </div> 1052 <div class="b2b-form-group"> 1053 <label>Official Email Address *</label> 1054 <input type="email" id="b2b-sender-email" value="${verifiedPartner.email || ''}" placeholder="[email protected]" required /> 1055 </div> 1056 </div> 1057 <div class="b2b-form-row"> 1058 <div class="b2b-form-group"> 1059 <label>Organization / Partner</label> 1060 <input type="text" id="b2b-sender-org" value="${verifiedPartner.company || ''}" placeholder="Company / institution name" /> 1061 </div> 1062 <div class="b2b-form-group"> 1063 <label>Phone / WhatsApp</label> 1064 <input type="tel" id="b2b-sender-phone" value="${verifiedPartner.phone || ''}" placeholder="+977 9XXXXXXX" /> 1065 </div> 1066 </div> 1067 <div class="b2b-form-group" style="margin-top: 8px;"> 1068 <label>Document Category</label> 1069 <select id="b2b-category"> 1070 <option value="Sub-Agent Student File Submission">Sub-Agent â Student File Submission</option> 1071 <option value="University Application Documents">University â Application Documents</option> 1072 <option value="Financial Documents">Financial / Bank Documents</option> 1073 <option value="SOP / LOR Drafts">SOP / LOR Drafts for Review</option> 1074 <option value="Visa Application Support">Visa Application Support</option> 1075 <option value="MOU / Partnership Agreement">MOU / Partnership Agreement</option> 1076 <option value="Student Transcripts & Marksheets">Student Transcripts & Marksheets</option> 1077 <option value="Other B2B Documents">Other B2B Documents</option> 1078 </select> 1079 </div> 1080 <div class="b2b-form-group" style="margin-top: 8px;"> 1081 <label>Notes / Student Reference (Optional)</label> 1082 <textarea id="b2b-notes" rows="3" placeholder="Student name, intake reference, or specific processing notes for Kavya Global team..."></textarea> 1083 </div> 1084 1085 <div style="display: flex; gap: 10px; margin-top: 14px; flex-wrap: wrap;"> 1086 <button type="button" class="btn-preview-b2b" onclick="window.previewB2bEmailDraft()" style="flex: 1;"> 1087 <i class="fa-solid fa-eye"></i> Preview Email 1088 </button>
1089 <button type="submit" id="btn-submit-b2b-files" class="btn-dispatch-b2b" style="flex: 2;"> 1090 <i class="fa-solid fa-paper-plane"></i> Send Documents to [email protected] 1091 </button> 1092 </div> 1093 <div id="b2b-dispatch-status" style="display:none; padding:14px 18px; border-radius:10px; font-size:13.5px; margin-top:14px;"></div> 1094 </form> 1095 </div> 1096 </div> 1097 `; 1098 1099 modal.innerHTML = ` 1100 <div class="lightbox-container" style="max-width: 960px; width: 95vw; max-height: 92vh; display: flex; flex-direction: column; background: #ffffff; border-radius: 16px; overflow: hidden; box-shadow: 0 25px 70px rgba(0,0,0,0.35);"> 1101 <div style="background: linear-gradient(135deg, #004a3e 0%, #002c25 100%); color: #ffffff; padding: 18px 24px; display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #fc9b09;"> 1102 <div style="display: flex; align-items: center; gap: 12px;"> 1103 <div style="width: 40px; height: 40px; background: rgba(255,255,255,0.15); border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 18px; color: #fc9b09;"> 1104 <i class="fa-solid fa-file-arrow-up"></i> 1105 </div> 1106 <div> 1107 <h3 style="margin: 0; font-size: 17px; font-weight: 800; color: #ffffff;">B2B Document Dispatch Portal</h3> 1108 <p style="margin: 2px 0 0; font-size: 12px; color: rgba(255,255,255,0.75);">Direct Document Transmission to [email protected]</p> 1109 </div> 1110 </div> 1111 <button onclick="window.closeDispatchModal()" style="color: #ffffff; background: transparent; border: none; font-size: 24px; cursor: pointer; padding: 4px 8px; line-height: 1;">×</button> 1112 </div> 1113 <div style="padding: 24px; overflow-y: auto; flex: 1; background: #fafcfb;"> 1114 ${bodyHtml} 1115 </div> 1116 </div> 1117 `; 1118 1119 modal.classList.add('active'); 1120 1121 if (isVerified) { 1122 setTimeout(() => { 1123 window.initB2bDropzone(); 1124 window.renderB2bReviewList(); 1125 }, 50); 1126 } 1127 }; 1128 1129 window.closeDispatchModal = function() { 1130 const modal = document.getElementById('b2b-dispatch-modal'); 1131 if (modal) modal.classList.remove('active'); 1132 }; 1133 1134 /* ============================================================= 1135 B2B DIRECT FILE DISPATCHER & REVIEW ENGINE 1136 ============================================================= */ 1137 window.b2bSelectedFiles = []; 1138 1139 function formatFileSize(bytes) { 1140 if (!bytes || bytes === 0) return '0 B'; 1141 const k = 1024; 1142 const sizes = ['B', 'KB', 'MB', 'GB']; 1143 const i = Math.floor(Math.log(bytes) / Math.log(k)); 1144 return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; 1145 } 1146 1147 function getB2bFileMeta(filename) { 1148 const ext = (filename.split('.').pop() || '').toLowerCase(); 1149 if (['pdf'].includes(ext)) return { icon: 'fa-file-pdf', color: '#e63946', label: 'PDF Document' }; 1150 if (['doc', 'docx'].includes(ext)) return { icon: 'fa-file-word', color: '#1d3557', label: 'Word Document' }; 1151 if (['xls', 'xlsx'].includes(ext)) return { icon: 'fa-file-excel', color: '#2a9d8f', label: 'Excel Sheet' }; 1152 if (['jpg', 'jpeg', 'png', 'webp'].includes(ext)) return { icon: 'fa-file-image', color: '#e76f51', label: 'Image File' }; 1153 if (['zip', 'rar'].includes(ext)) return { icon: 'fa-file-zipper', color: '#6a4c93', label: 'Archive Zip' }; 1154 return { icon: 'fa-file-lines', color: '#004a3e', label: 'Document' }; 1155 } 1156 1157 function readFileAsBase64(file) { 1158 return new Promise((resolve, reject) => { 1159 const reader = new FileReader(); 1160 reader.onload = () => resolve(reader.result); 1161 reader.onerror = error => reject(error); 1162 reader.readAsDataURL(file); 1163 }); 1164 } 1165 1166 window.handleB2bFilesSelected = async function (fileList) { 1167 if (!fileList || fileList.length === 0) return; 1168 1169 for (let i = 0; i < fileList.length; i++) { 1170 const file = fileList[i]; 1171 if (file.size > 15 * 1024 * 1024) { 1172 alert(`File "${file.name}" exceeds the 15MB single file limit. Please select a smaller file.`); 1173 continue; 1174 } 1175 if (window.b2bSelectedFiles.some(f => f.filename === file.name && f.size === file.size)) { 1176 continue; 1177 }
1178 try { 1179 const base64 = await readFileAsBase64(file); 1180 const meta = getB2bFileMeta(file.name); 1181 const isImage = (file.type && file.type.startsWith('image/')) || 1182 ['jpg', 'jpeg', 'png', 'webp'].includes((file.name.split('.').pop() || '').toLowerCase()); 1183 window.b2bSelectedFiles.push({ 1184 filename: file.name, 1185 size: file.size, 1186 sizeFormatted: formatFileSize(file.size), 1187 type: file.type || 'application/octet-stream', 1188 icon: meta.icon, 1189 color: meta.color, 1190 label: meta.label, 1191 isImage: isImage, 1192 base64: base64 1193 }); 1194 } catch (err) { 1195 console.error('Error reading file:', file.name, err); 1196 } 1197 } 1198 window.renderB2bReviewList(); 1199 }; 1200 1201 window.removeB2bFile = function (idx) { 1202 if (window.b2bSelectedFiles && window.b2bSelectedFiles[idx]) { 1203 window.b2bSelectedFiles.splice(idx, 1); 1204 window.renderB2bReviewList(); 1205 } 1206 }; 1207 1208 window.clearAllB2bFiles = function () { 1209 window.b2bSelectedFiles = []; 1210 const input = document.getElementById('b2b-file-input'); 1211 if (input) input.value = ''; 1212 window.renderB2bReviewList(); 1213 }; 1214 1215 window.resetB2bPortalForm = function () { 1216 window.b2bSelectedFiles = []; 1217 const input = document.getElementById('b2b-file-input'); 1218 if (input) input.value = ''; 1219 const form = document.getElementById('b2b-file-dispatch-form'); 1220 if (form) form.reset(); 1221 const statusDiv = document.getElementById('b2b-dispatch-status'); 1222 if (statusDiv) { 1223 statusDiv.style.display = 'none'; 1224 statusDiv.innerHTML = ''; 1225 } 1226 window.renderB2bReviewList(); 1227 }; 1228 1229 window.renderB2bReviewList = function () { 1230 const container = document.getElementById('b2b-review-container'); 1231 if (!container) return; 1232 1233 if (!window.b2bSelectedFiles || window.b2bSelectedFiles.length === 0) { 1234 container.innerHTML = ` 1235 <div class="b2b-no-files-notice"> 1236 <div class="b2b-notice-icon"><i class="fa-solid fa-file-circle-question"></i></div> 1237 <div class="b2b-notice-text"> 1238 <strong>No documents attached yet.</strong> 1239 <span>Drag & drop files above or click Browse to verify them before dispatching directly to [email protected].</span> 1240 </div> 1241 </div> 1242 `; 1243 return; 1244 } 1245 1246 let totalBytes = 0; 1247 window.b2bSelectedFiles.forEach(f => totalBytes += f.size); 1248 const totalFormatted = formatFileSize(totalBytes); 1249 const maxLimitBytes = 25 * 1024 * 1024; 1250 const capacityPct = Math.min(100, Math.round((totalBytes / maxLimitBytes) * 100)); 1251 const isExceeded = totalBytes > maxLimitBytes; 1252 const barColor = isExceeded ? '#dc3545' : (capacityPct > 80 ? '#fc9b09' : '#004a3e'); 1253 1254 const listHtml = window.b2bSelectedFiles.map((file, idx) => { 1255 return ` 1256 <div class="b2b-review-item"> 1257 ${file.isImage ? ` 1258 <div class="b2b-item-thumb-wrap"> 1259 <img src="${file.base64}" alt="${file.filename}" class="b2b-item-thumb" /> 1260 </div> 1261 ` : ` 1262 <div class="b2b-item-icon" style="color: ${file.color}; background: ${file.color}15;"> 1263 <i class="fa-solid ${file.icon}"></i> 1264 </div> 1265 `} 1266 <div class="b2b-item-details"> 1267 <div class="b2b-item-name" title="${file.filename}">${file.filename}</div> 1268 <div class="b2b-item-meta"> 1269 <span class="b2b-file-size">${file.sizeFormatted}</span> 1270 <span class="b2b-file-type">${file.label}</span> 1271 <span class="b2b-status-verified"><i class="fa-solid fa-circle-check"></i> Ready to Send</span> 1272 </div> 1273 </div> 1274 <div class="b2b-item-actions"> 1275 <button type="button" class="btn-remove-b2b-file" onclick="window.removeB2bFile(${idx})" title="Remove ${file.filename}"> 1276 <i class="fa-solid fa-trash-can"></i> 1277 </button> 1278 </div> 1279 </div> 1280 `; 1281 }).join(''); 1282 1283 container.innerHTML = ` 1284 <div class="b2b-capacity-meter-wrap"> 1285 <div class="b2b-capacity-bar-header">
1286 <span class="b2b-cap-label"><i class="fa-solid fa-hard-drive"></i> Total Attachment Size: <strong>${totalFormatted}</strong> / 25.0 MB</span> 1287 <span class="b2b-cap-pct" style="color: ${barColor}; font-weight: 800;">${capacityPct}%</span> 1288 </div> 1289 <div class="b2b-capacity-bar"> 1290 <div class="b2b-capacity-fill" style="width: ${capacityPct}%; background: ${barColor};"></div> 1291 </div> 1292 ${isExceeded ? ` 1293 <div class="b2b-capacity-alert"> 1294 <i class="fa-solid fa-triangle-exclamation"></i> Total size exceeds the 25MB email limit. Please remove some files before sending. 1295 </div> 1296 ` : ''} 1297 </div> 1298 1299 <div class="b2b-review-summary-bar"> 1300 <div class="b2b-summary-left"> 1301 <span class="b2b-count-badge"><i class="fa-solid fa-folder-open"></i> ${window.b2bSelectedFiles.length} Document${window.b2bSelectedFiles.length > 1 ? 's' : ''} Ready</span> 1302 </div> 1303 <div class="b2b-summary-right"> 1304 <button type="button" class="btn-add-more-files" onclick="document.getElementById('b2b-file-input').click();"> 1305 <i class="fa-solid fa-plus"></i> Add More 1306 </button> 1307 <button type="button" class="btn-clear-all-files" onclick="window.clearAllB2bFiles();" title="Remove all files"> 1308 <i class="fa-solid fa-trash-can"></i> Clear All 1309 </button> 1310 </div> 1311 </div> 1312 1313 <div class="b2b-review-list"> 1314 ${listHtml} 1315 </div> 1316 1317 <div class="b2b-review-foot-note"> 1318 <i class="fa-solid fa-shield-halved" style="color: #004a3e;"></i> 1319 <span><strong>${window.b2bSelectedFiles.length} file(s) attached</strong> and ready to send directly to <code>[email protected]</code>.</span> 1320 </div> 1321 `; 1322 }; 1323 1324 window.closeB2bEmailPreview = function () { 1325 const modal = document.getElementById('b2b-email-preview-modal'); 1326 if (modal) modal.remove(); 1327 }; 1328 1329 window.previewB2bEmailDraft = function () { 1330 const name = (document.getElementById('b2b-sender-name') || {}).value || 'Not provided yet'; 1331 const email = (document.getElementById('b2b-sender-email') || {}).value || 'Not provided yet'; 1332 const org = (document.getElementById('b2b-sender-org') || {}).value || ''; 1333 const phone = (document.getElementById('b2b-sender-phone') || {}).value || ''; 1334 const category = (document.getElementById('b2b-category') || {}).value || 'B2B Document Submission'; 1335 const notes = (document.getElementById('b2b-notes') || {}).value || ''; 1336 1337 const files = window.b2bSelectedFiles || []; 1338 let totalBytes = 0; 1339 files.forEach(f => totalBytes += f.size); 1340 const totalMb = (totalBytes / (1024 * 1024)).toFixed(2); 1341 1342 const filesRows = files.length > 0 ? files.map((f, idx) => ` 1343 <tr style="border-bottom: 1px solid #edf2f0;"> 1344 <td style="padding: 8px 10px; font-size: 12.5px; color: #00332a; font-weight: 600;"> 1345 #${idx + 1} • ${f.filename} 1346 </td> 1347 <td style="padding: 8px 10px; font-size: 11.5px; color: #555; text-align: right;"> 1348 ${(f.size / (1024 * 1024)).toFixed(2)} MB 1349 </td> 1350 <td style="padding: 8px 10px; font-size: 11.5px; text-align: right;"> 1351 <span style="background: #e8f5f1; color: #004a3e; padding: 2px 8px; border-radius: 4px; font-weight: 700;">ATTACHED</span> 1352 </td> 1353 </tr> 1354 `).join('') : ` 1355 <tr> 1356 <td colspan="3" style="padding: 14px; text-align: center; color: #888; font-style: italic;"> 1357 (No documents attached yet â upload files on the left to include attachments) 1358 </td> 1359 </tr> 1360 `; 1361 1362 const subjectLine = `ð B2B Direct Document: [${category}] from ${name}${org ? ' (' + org + ')' : ''}`; 1363 1364 let modal = document.getElementById('b2b-email-preview-modal'); 1365 if (!modal) { 1366 modal = document.createElement('div'); 1367 modal.id = 'b2b-email-preview-modal'; 1368 modal.className = 'lightbox-overlay active'; 1369 document.body.appendChild(modal); 1370 } 1371 1372 modal.innerHTML = ` 1373 <div class="lightbox-container" style="max-width: 720px; width: 92vw; max-height: 90vh; display: flex; flex-direction: column; background: #ffffff; border-radius: 14px; overflow: hidden; box-shadow: 0 20px 60px rgba(0,0,0,0.3);"> 1374 <div class="lightbox-header" style="background: #00332a; color: #ffffff; padding: 14px 20px; display: flex; justify-content: space-between; align-items: center;"> 1375 <h3 style="margin: 0; font-size: 16px; color: #ffffff; display: flex; align-items: center; gap: 8px;"> 1376 <i class="fa-solid fa-envelope-open-text" style="color: #fc9b09;"></i> Live Email Transmission Preview 1377 </h3> 1378 <button onclick="window.closeB2bEmailPreview()" class="lightbox-close-btn" style="color: #fff; background: transparent; border: none; font-size: 22px; cursor: pointer;">×</button> 1379 </div> 1380 1381 <div style="background: #f4f8f7; padding: 12px 20px; border-bottom: 1px solid #e0ece8; font-size: 12.5px; color: #00332a;"> 1382 <div style="display: flex; gap: 8px; margin-bottom: 4px;"> 1383 <strong style="width: 70px; color: #555;">To:</strong>
1384 <span style="font-weight: 700; color: #004a3e;">[email protected]</span> 1385 </div> 1386 <div style="display: flex; gap: 8px; margin-bottom: 4px;"> 1387 <strong style="width: 70px; color: #555;">CC:</strong> 1388 <span style="color: #666;">[email protected]</span> 1389 </div> 1390 <div style="display: flex; gap: 8px; margin-bottom: 4px;"> 1391 <strong style="width: 70px; color: #555;">Reply-To:</strong> 1392 <span>${email}</span> 1393 </div> 1394 <div style="display: flex; gap: 8px;"> 1395 <strong style="width: 70px; color: #555;">Subject:</strong> 1396 <span style="color: #00332a; font-weight: 700;">${subjectLine}</span> 1397 </div> 1398 </div> 1399 1400 <div style="padding: 20px; overflow-y: auto; flex: 1; background: #fafcfb;"> 1401 <div style="background: #ffffff; border: 1px solid #e0e9e7; border-radius: 10px; overflow: hidden; box-shadow: 0 2px 10px rgba(0,0,0,0.04);"> 1402 <div style="background: linear-gradient(135deg, #004a3e 0%, #00221c 100%); padding: 18px 22px; text-align: center; color: #ffffff;"> 1403 <h2 style="margin: 0 0 4px 0; font-size: 18px; font-weight: 800;">Kavya Global Network</h2> 1404 <p style="margin: 0; font-size: 11.5px; color: #fc9b09; font-weight: 700; letter-spacing: 0.5px;">B2B DOCUMENT DISPATCH • KAVYA GLOBAL NETWORK</p> 1405 </div> 1406 1407 <div style="padding: 20px;"> 1408 <div style="background: #f0f7f5; border-left: 4px solid #fc9b09; padding: 10px 14px; border-radius: 6px; margin-bottom: 16px;"> 1409 <p style="margin: 0; font-size: 13px; color: #00332a; font-weight: 700;"> 1410 <strong>Category:</strong> <span style="color: #fc9b09;">${category}</span> 1411 </p> 1412 <p style="margin: 3px 0 0 0; font-size: 11px; color: #666;"> 1413 Received: ${new Date().toLocaleString('en-US', { timeZone: 'Asia/Kathmandu' })} (Nepal Time) 1414 </p> 1415 </div> 1416 1417 <h4 style="margin: 0 0 8px 0; color: #004a3e; font-size: 13.5px; border-bottom: 2px solid #eef3f1; padding-bottom: 4px;">Sender & Organization Information</h4> 1418 <table style="width: 100%; border-collapse: collapse; font-size: 13px; margin-bottom: 18px;"> 1419 <tbody> 1420 <tr style="border-bottom: 1px solid #edf2f0;"> 1421 <td style="padding: 7px 0; font-weight: 700; color: #555; width: 140px;">Contact Person:</td> 1422 <td style="padding: 7px 0; font-weight: 700; color: #00332a;">${name}</td> 1423 </tr> 1424 ${org ? ` 1425 <tr style="border-bottom: 1px solid #edf2f0;"> 1426 <td style="padding: 7px 0; font-weight: 700; color: #555;">Organization:</td> 1427 <td style="padding: 7px 0; color: #00332a; font-weight: 600;">${org}</td> 1428 </tr>` : ''} 1429 <tr style="border-bottom: 1px solid #edf2f0;"> 1430 <td style="padding: 7px 0; font-weight: 700; color: #555;">Email Address:</td> 1431 <td style="padding: 7px 0; color: #006051; font-weight: 600;">${email}</td> 1432 </tr> 1433 ${phone ? ` 1434 <tr style="border-bottom: 1px solid #edf2f0;"> 1435 <td style="padding: 7px 0; font-weight: 700; color: #555;">Phone / WhatsApp:</td> 1436 <td style="padding: 7px 0; color: #25d366; font-weight: 700;">${phone}</td> 1437 </tr>` : ''} 1438 ${notes ? ` 1439 <tr style="border-bottom: 1px solid #edf2f0;"> 1440 <td style="padding: 7px 0; font-weight: 700; color: #555; vertical-align: top;">Notes / Message:</td> 1441 <td style="padding: 7px 0; color: #444; line-height: 1.4;">${notes.replace(/\n/g, '<br>')}</td> 1442 </tr>` : ''} 1443 </tbody> 1444 </table> 1445 1446 <h4 style="margin: 0 0 8px 0; color: #004a3e; font-size: 13.5px; border-bottom: 2px solid #eef3f1; padding-bottom: 4px;"> 1447 Attached Files (${files.length} file${files.length !== 1 ? 's' : ''} • ${totalMb} MB total) 1448 </h4> 1449 <table style="width: 100%; border-collapse: collapse; margin-bottom: 18px; background: #fafcfb; border: 1px solid #edf2f0; border-radius: 6px;"> 1450 <thead> 1451 <tr style="background: #f0f7f5; border-bottom: 1px solid #e0ece8;"> 1452 <th style="padding: 6px 10px; font-size: 11.5px; text-align: left; color: #004a3e;">File Name</th> 1453 <th style="padding: 6px 10px; font-size: 11.5px; text-align: right; color: #004a3e;">Size</th> 1454 <th style="padding: 6px 10px; font-size: 11.5px; text-align: right; color: #004a3e;">Status</th> 1455 </tr> 1456 </thead> 1457 <tbody> 1458 ${filesRows} 1459 </tbody> 1460 </table> 1461 1462 <div style="background: #eef7f4; border: 1px solid #c8e6dc; padding: 10px 14px; border-radius: 6px; font-size: 11.5px; color: #004a3e;"> 1463 <p style="margin: 0;"><i class="fa-solid fa-lock"></i> Files are sent directly to <strong>[email protected]</strong> via encrypted email.</p> 1464 </div> 1465 </div> 1466 </div> 1467 </div> 1468 1469 <div style="background: #fafcfb; padding: 12px 20px; border-top: 1px solid #eef3f1; display: flex; justify-content: space-between; align-items: center;">
1470 <span style="font-size: 12px; color: #666;"><i class="fa-solid fa-circle-info" style="color: #fc9b09;"></i> This is the exact layout delivered directly to <strong>[email protected]</strong></span> 1471 <button onclick="window.closeB2bEmailPreview()" style="background: #004a3e; color: #fff; border: none; padding: 8px 18px; border-radius: 20px; font-weight: 700; font-size: 12.5px; cursor: pointer;"> 1472 Close Preview 1473 </button> 1474 </div> 1475 </div> 1476 `; 1477 }; 1478 1479 window.KavyaSubmitB2bFiles = async function (form) { 1480 const statusDiv = document.getElementById('b2b-dispatch-status'); 1481 const submitBtn = document.getElementById('btn-submit-b2b-files'); 1482 const origHtml = submitBtn ? submitBtn.innerHTML : ''; 1483 1484 if (!window.b2bSelectedFiles || window.b2bSelectedFiles.length === 0) { 1485 if (statusDiv) { 1486 statusDiv.style.display = 'block'; 1487 statusDiv.style.background = '#fff3cd'; 1488 statusDiv.style.color = '#856404'; 1489 statusDiv.style.borderLeft = '4px solid #ffeeba'; 1490 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> <strong>No files attached:</strong> Please drag & drop or browse at least one document to review and send.'; 1491 statusDiv.scrollIntoView({ behavior: 'smooth', block: 'center' }); 1492 } 1493 return; 1494 } 1495 1496 let totalBytes = 0; 1497 window.b2bSelectedFiles.forEach(f => totalBytes += f.size); 1498 if (totalBytes > 25 * 1024 * 1024) { 1499 if (statusDiv) { 1500 statusDiv.style.display = 'block'; 1501 statusDiv.style.background = '#f8d7da'; 1502 statusDiv.style.color = '#721c24'; 1503 statusDiv.style.borderLeft = '4px solid #dc3545'; 1504 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> <strong>Size Exceeded:</strong>
1504 Total attachment size exceeds the 25MB email limit. Please remove some files.'; 1505 statusDiv.scrollIntoView({ behavior: 'smooth', block: 'center' }); 1506 } 1507 return; 1508 } 1509 1510 const name = (document.getElementById('b2b-sender-name') || {}).value || ''; 1511 const email = (document.getElementById('b2b-sender-email') || {}).value || ''; 1512 const org = (document.getElementById('b2b-sender-org') || {}).value || ''; 1513 const phone = (document.getElementById('b2b-sender-phone') || {}).value || ''; 1514 const category = (document.getElementById('b2b-category') || {}).value || 'B2B Document Submission'; 1515 const notes = (document.getElementById('b2b-notes') || {}).value || ''; 1516 1517 if (!name.trim()) { 1518 if (statusDiv) { 1519 statusDiv.style.display = 'block'; 1520 statusDiv.style.background = '#f8d7da'; 1521 statusDiv.style.color = '#721c24'; 1522 statusDiv.style.borderLeft = '4px solid #dc3545'; 1523 statusDiv.innerHTML = '<i class="fa-solid fa-circle-exclamation"></i> Please enter your contact person name.'; 1524 statusDiv.scrollIntoView({ behavior: 'smooth', block: 'center' }); 1525 } 1526 return; 1527 } 1528 1529 if (!email.trim() || !validateEmail(email)) { 1530 if (statusDiv) { 1531 statusDiv.style.display = 'block'; 1532 statusDiv.style.background = '#f8d7da'; 1533 statusDiv.style.color = '#721c24'; 1534 statusDiv.style.borderLeft = '4px solid #dc3545'; 1535 statusDiv.innerHTML = '<i class="fa-solid fa-circle-exclamation"></i> Please enter a valid official email address (e.g. [email protected]).'; 1536 statusDiv.scrollIntoView({ behavior: 'smooth', block: 'center' }); 1537 } 1538 return; 1539 } 1540 1541 if (phone.trim() && !validatePhone(phone)) { 1542 if (statusDiv) { 1543 statusDiv.style.display = 'block'; 1544 statusDiv.style.background = '#f8d7da'; 1545 statusDiv.style.color = '#721c24'; 1546 statusDiv.style.borderLeft = '4px solid #dc3545'; 1547 statusDiv.innerHTML = '<i class="fa-solid fa-circle-exclamation"></i> Please enter a valid phone or WhatsApp number (minimum 7 digits).'; 1548 statusDiv.scrollIntoView({ behavior: 'smooth', block: 'center' }); 1549 } 1550 return; 1551 } 1552 1553 if (submitBtn) { 1554 submitBtn.disabled = true; 1555 submitBtn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Encrypting & Dispatching directly to [email protected]...'; 1556 } 1557 1558 if (statusDiv) { 1559 statusDiv.style.display = 'block'; 1560 statusDiv.style.background = '#e8f4f8'; 1561 statusDiv.style.color = '#0c5460'; 1562 statusDiv.style.borderLeft = '4px solid #17a2b8'; 1563 statusDiv.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i> Sending documents to [email protected], please wait...'; 1564 } 1565 1566 const payload = { 1567 senderName: name, 1568 senderEmail: email, 1569 senderPhone: phone, 1570 organization: org, 1571 category: category, 1572 message: notes, 1573 files: window.b2bSelectedFiles.map(f => ({ 1574 filename: f.filename, 1575 contentType: f.type, 1576 size: f.size, 1577 base64: f.base64 1578 })) 1579 }; 1580 1581 try { 1582 const res = await fetch('/api/b2b-send-files', { 1583 method: 'POST', 1584 headers: { 'Content-Type': 'application/json' }, 1585 body: JSON.stringify(payload) 1586 }); 1587 1588 const data = await res.json(); 1589 1590 if (data.success) { 1591 const filesCount = window.b2bSelectedFiles.length; 1592 window.b2bSelectedFiles = []; 1593 const fileInput = document.getElementById('b2b-file-input'); 1594 if (fileInput) fileInput.value = ''; 1595 window.renderB2bReviewList(); 1596 form.reset(); 1597 1598 if (statusDiv) { 1599 statusDiv.style.display = 'block'; 1600 statusDiv.style.background = '#d4edda'; 1601 statusDiv.style.color = '#155724'; 1602 statusDiv.style.borderLeft = '4px solid #28a745'; 1603 statusDiv.innerHTML = ` 1604 <div style="font-size: 16.5px; font-weight: 800; margin-bottom: 6px; color: #0f5132;"> 1605 <i class="fa-solid fa-circle-check" style="color: #28a745; font-size: 22px;"></i> Documents Dispatched Successfully! 1606 </div> 1607 <div style="font-size: 13.5px; line-height: 1.6; margin-bottom: 12px; color: #155724;"> 1608 <strong>${filesCount} file(s)</strong> have been transmitted directly to <strong>[email protected]</strong> with copy to <strong>[email protected]</strong>. Our senior partnerships executive will review and follow up with <strong>${email}</strong>. 1609 </div> 1610 <div style="background: rgba(255,255,255,0.75); padding: 10px 14px; border-radius: 8px; font-size: 12px; margin-bottom: 14px; color: #004a3e; border: 1px solid #c3e6cb;"> 1611 <i class="fa-solid fa-lock"></i> Your files were delivered securely and directly to our inbox. No files were stored on this website's server. 1612 </div> 1613 <div style="display: flex; gap: 10px; flex-wrap: wrap;"> 1614 <a href="https://wa.me/9779709040360?text=${encodeURIComponent('Hello Kavya Global Corporate Desk, I have just sent documents to [email protected] regarding ' + category + ' from ' + (org || name))}" target="_blank" style="display: inline-flex; align-items: center; gap: 6px; background: #25d366; color: #fff; text-decoration: none; padding: 9px 18px; border-radius: 25px; font-weight: 700; font-size: 13px;"> 1615 <i class="fa-brands fa-whatsapp"></i>
1615 Notify Corporate Desk on WhatsApp 1616 </a> 1617 <button type="button" onclick="window.resetB2bPortalForm()" style="background: #004a3e; color: #ffffff; border: none; padding: 9px 18px; border-radius: 25px; font-weight: 700; font-size: 13px; cursor: pointer;"> 1618 <i class="fa-solid fa-plus"></i> Send Another Document Batch 1619 </button> 1620 </div> 1621 `; 1622 statusDiv.scrollIntoView({ behavior: 'smooth', block: 'center' }); 1623 } 1624 } else { 1625 if (statusDiv) { 1626 statusDiv.style.display = 'block'; 1627 statusDiv.style.background = '#fff5f5'; 1628 statusDiv.style.color = '#721c24'; 1629 statusDiv.style.borderLeft = '4px solid #dc3545'; 1630 statusDiv.innerHTML = ` 1631 <div style="font-size: 15px; font-weight: 800; color: #dc3545; margin-bottom: 6px;"> 1632 <i class="fa-solid fa-triangle-exclamation"></i> SMTP Transmission Notice 1633 </div> 1634 <div style="font-size: 13px; line-height: 1.5; margin-bottom: 12px; color: #555;"> 1635 ${data.message || 'SMTP Authentication failed. The Google App Password in server configuration must be updated.'} 1636 </div> 1637 <div style="display: flex; gap: 8px; flex-wrap: wrap;"> 1638 <a href="mailto:[email protected]?subject=${encodeURIComponent('B2B Document Submission from ' + name + (org ? ' (' + org + ')' : ''))}" style="display: inline-flex; align-items: center; gap: 6px; background: #004a3e; color: #ffffff; text-decoration: none; padding: 8px 16px; border-radius: 20px; font-weight: 700; font-size: 12.5px;"> 1639 <i class="fa-solid fa-envelope"></i> Send Directly via Email Client 1640 </a> 1641 <button type="button" onclick="window.previewB2bEmailDraft()" style="background: #fc9b09; color: #00221c; border: none; padding: 8px 16px; border-radius: 20px; font-weight: 700; font-size: 12.5px; cursor: pointer;"> 1642 <i class="fa-solid fa-eye"></i> View Email Layout Preview 1643 </button> 1644 </div> 1645 `; 1646 statusDiv.scrollIntoView({ behavior: 'smooth', block: 'center' }); 1647 } 1648 } 1649 } catch (err) { 1650 if (statusDiv) { 1651 statusDiv.style.display = 'block'; 1652 statusDiv.style.background = '#f8d7da'; 1653 statusDiv.style.color = '#721c24'; 1654 statusDiv.style.borderLeft = '4px solid #dc3545'; 1655 statusDiv.innerHTML = `<i class="fa-solid fa-triangle-exclamation"></i> <strong>Network Notice:</strong> ${err.message}. You can also email documents directly to <a href="mailto:[email protected]" style="color: #721c24; font-weight: bold; text-decoration: underline;">[email protected]</a>.`; 1656 } 1657 } finally { 1658 if (submitBtn) { 1659 submitBtn.disabled = false; 1660 submitBtn.innerHTML = origHtml; 1661 } 1662 } 1663 }; 1664 1665 window.KavyaLoginPartner = async function (form) { 1666 const input = document.getElementById('b2b-partner-id-input'); 1667 const statusDiv = document.getElementById('b2b-login-status'); 1668 const partnerId = input ? input.value.trim() : ''; 1669 1670 if (!partnerId) { 1671 if (statusDiv) { 1672 statusDiv.style.display = 'block'; 1673 statusDiv.style.background = '#fff3cd'; 1674 statusDiv.style.color = '#856404'; 1675 statusDiv.style.borderLeft = '4px solid #ffeeba'; 1676 statusDiv.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Please enter your Unique Partner ID.'; 1677 } 1678 return; 1679 } 1680 1681 const btn = form.querySelector('button[type="submit"]'); 1682 const origHtml = btn ? btn.innerHTML : ''; 1683 if (btn) { 1684 btn.disabled = true; 1685 btn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Verifying ID...'; 1686 } 1687 1688 try { 1689 const res = await fetch('/api/partner-verify', { 1690 method: 'POST', 1691 headers: { 'Content-Type': 'application/json' }, 1692 body: JSON.stringify({ partnerId }) 1693 }); 1694 const data = await res.json(); 1695 if (data.success && data.partner) { 1696 verifiedPartner = data.partner; 1697 try { 1698 localStorage.setItem('kgn_verified_partner', JSON.stringify(data.partner)); 1699 } catch (e) {} 1700 renderApp(); 1701 const dispatchModal = document.getElementById('b2b-dispat
1701ch-modal'); 1702 if (dispatchModal && dispatchModal.classList.contains('active')) { 1703 window.openDispatchModal(); 1704 } 1705 } else { 1706 if (statusDiv) { 1707 statusDiv.style.display = 'block'; 1708 statusDiv.style.background = '#f8d7da'; 1709 statusDiv.style.color = '#721c24'; 1710 statusDiv.style.borderLeft = '4px solid #dc3545'; 1711 statusDiv.innerHTML = `<i class="fa-solid fa-circle-xmark"></i> ${data.message || 'Invalid Partner ID.'}`; 1712 } 1713 } 1714 } catch (err) { 1715 if (statusDiv) { 1716 statusDiv.style.display = 'block'; 1717 statusDiv.style.background = '#f8d7da'; 1718 statusDiv.style.color = '#721c24'; 1719 statusDiv.style.borderLeft = '4px solid #dc3545'; 1720 statusDiv.innerHTML = `<i class="fa-solid fa-triangle-exclamation"></i> Network error: ${err.message}`; 1721 } 1722 } finally { 1723 if (btn) { 1724 btn.disabled = false; 1725 btn.innerHTML = origHtml; 1726 } 1727 } 1728 }; 1729 1730 window.KavyaLogoutPartner = function () { 1731 verifiedPartner = null; 1732 try { 1733 localStorage.removeItem('kgn_verified_partner'); 1734 } catch (e) {} 1735 renderApp(); 1736 const dispatchModal = document.getElementById('b2b-dispatch-modal'); 1737 if (dispatchModal && dispatchModal.classList.contains('active')) { 1738 window.openDispatchModal(); 1739 } 1740 }; 1741 1742 window.initB2bDropzone = function () { 1743 const dropzone = document.getElementById('b2b-dropzone'); 1744 if (!dropzone) return; 1745 1746 ['dragenter', 'dragover'].forEach(eventName => { 1747 dropzone.addEventListener(eventName, (e) => { 1748 e.preventDefault(); 1749 e.stopPropagation(); 1750 dropzone.classList.add('b2b-drop-active'); 1751 }, false); 1752 }); 1753 1754 ['dragleave', 'drop'].forEach(eventName => { 1755 dropzone.addEventListener(eventName, (e) => { 1756 e.preventDefault(); 1757 e.stopPropagation(); 1758 dropzone.classList.remove('b2b-drop-active'); 1759 }, false); 1760 }); 1761 1762 dropzone.addEventListener('drop', (e) => { 1763 const dt = e.dataTransfer; 1764 const files = dt ? dt.files : null; 1765 if (files && files.length > 0) { 1766 window.handleB2bFilesSelected(files); 1767 } 1768 }, false); 1769 }; 1770 1771 /* Main App Renderer */ 1772 function renderApp() { 1773 const root = document.getElementById('app'); 1774 if (!root || !siteData) return; 1775 1776 const currentPath = (window.location.pathname.replace(/\/$/, '') || '/').toLowerCase(); 1777 const currentHash = (window.location.hash || '').toLowerCase(); 1778 1779 const isPathAdmin = currentPath === '/admin'; 1780 const isHashAdmin = currentHash === '#admin' || currentHash.startsWith('#admin'); 1781 const showAdmin = isAdminOpen || isPathAdmin || isHashAdmin; 1782 const isAuthenticated = sessionStorage.getItem('kgn_admin_authenticated') === 'true'; 1783 1784 // If Admin mode is active, render dedicated Full-Screen Admin Portal 1785 if (showAdmin) { 1786 root.innerHTML = isAuthenticated ? renderAdminPortal() : renderAdminLoginPage(); 1787 bindEvents(); 1788 return; 1789 } 1790 1791 const isFullWidth = siteData.general && siteData.general.layoutMode === 'full-width'; 1792 const wrapperClass = isFullWidth ? 'full-width-site-wrapper' : 'boxed-site-wrapper'; 1793 1794 let mainContentHtml = ''; 1795 let pageTitle = 'Kavya Global Network | #1 Education Consultancy in Nepal for USA, Australia, UK &
1795Canada'; 1796 let pageDesc = 'Premier MOEST-licensed education consultancy in Kathmandu, Nepal representing top universities in Australia, Canada, UK, USA, Japan, Korea, and Germany.'; 1797 1798 const isB2bDomain = typeof window !== 'undefined' && window.location && ( 1799 window.location.hostname.startsWith('b2b.') 1800 ); 1801 const isB2bRoute = currentPath === '/b2b' || 1802 currentPath === '/b2b-portal' || 1803 currentPath === '/b2b/dispatch' || 1804 currentPath === '/partner-with-us' || 1805 currentPath === '/partnerships' || 1806 currentPath === '/partner'; 1807 1808 // Route matching for all menu & sub-menu pages 1809 if (isB2bRoute || (isB2bDomain && (currentPath === '/' || currentPath === ''))) { 1810 pageTitle = 'B2B Document Portal & Institutional Exchange | Kavya Global Network'; 1811 pageDesc = 'Official B2B Gateway for Universities, Colleges & Sub-Agents. Upload and dispatch documents directly to [email protected]. Govt. Registered ⢠MOEST Approval in Process.'; 1812 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderPartnerWithUsPage(siteData, verifiedPartner) : ''; 1813 } else if (currentPath === '/about' || currentHash === '#about-page') { 1814 pageTitle = 'About Kavya Global Network | Best Education Consultancy in Nepal'; 1815 pageDesc = 'Learn about Kavya Global Network Nepal Pvt. Ltd., founded in 2016 in New Baneshwor, Kathmandu (Govt. Regd. ⢠MOEST Approval in Process).'; 1816 mainContentHtml = renderAboutPage(); 1817 } else if (currentPath === '/leadership' || currentPath === '/leadership-message' || currentHash === '#leadership-page') { 1818 pageTitle = 'Leadership Message | Managing Director & Founder | Kavya Global Network'; 1819 pageDesc = 'Read the guiding philosophy and student-first commitment from the Managing Director of Kavya Global Network.'; 1820 mainContentHtml = renderLeadershipMessagePage(); 1821 } else if (currentPath === '/accreditations' || currentPath === '/licenses') { 1822 pageTitle = 'Accreditations & Government Affiliations | Kavya Global Network'; 1823 pageDesc = 'Official credentials: Govt. Registered Company, MOEST Approval in Process, British Council Certified, ICEF Accredited Agency #7027, and Pearson official testing partners.'; 1824 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderAccreditationsPage(siteData) : renderAccreditationsSection(); 1825 } else if (currentPath === '/visa-success' || currentPath === '/visa-gallery') {
1826 pageTitle = 'Visa Success Stories & Grants (98% Visa Success Rate) | Kavya Global Network'; 1827 pageDesc = 'Browse authentic student visa grants and scholarship awards for Australia, Canada, UK, USA, and Europe from Nepal.'; 1828 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderVisaSuccessPage(siteData) : renderVisaSuccessGallery(); 1829 } else if (currentPath === '/destinations') { 1830 pageTitle = 'Top Study Abroad Destinations for Nepalese Students (2025-2026) | Kavya Global'; 1831 pageDesc = 'Compare tuition fees, intakes, post-study work permits, and PR pathways across Australia, Canada, UK, USA, Japan, Korea, and Germany.'; 1832 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderDestinationsOverviewPage(siteData) : renderDestinationsSection(); 1833 } else if (currentPath.startsWith('/destinations/') || currentPath.startsWith('/study-in-')) { 1834 const cKey = currentPath.replace('/destinations/', '').replace('/study-in-', ''); 1835 const titles = { 1836 australia: 'Study in Australia from Nepal | Student Visa Australia, Cost & PR Pathways', 1837 canada: 'Study in Canada from Nepal | Cost of Studying in Canada, Visas & PGWP', 1838 uk: 'Study in UK from Nepal | 1-Year Master\'s, MBA Abroad & Graduate Route Visa', 1839 usa: 'Study in USA from Nepal | Scholarships for Nepali Students, F-1 Visa & STEM OPT', 1840 japan: 'Study in Japan from Nepal | Language Institutes, 28-Hour Work & High Employment', 1841 korea: 'Study in Korea from Nepal | GKS Scholarships, D-2/D-4 Visas & STEM Degrees', 1842 germany: 'Study in Germany from Nepal | Tuition-Free Public Universities & Student Visa' 1843 }; 1844 if (titles[cKey]) pageTitle = titles[cKey] + ' | Kavya Global'; 1845 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderDestinationDetailPage(cKey, siteData) : renderDestinationsSection(); 1846 } else if (currentPath === '/services' || currentPath === '/our-services') { 1847 pageTitle = 'Overseas Education Services in Kathmandu | Best Education Consultancy in Nepal'; 1848 pageDesc = 'Comprehensive services: Career counseling, university admissions, visa documentation, mock interviews, and pre-departure briefings.'; 1849 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderServicesOverviewPage(siteData) : renderServicesSection(); 1850 } else if (currentPath.startsWith('/services/')) { 1851 const sKey = currentPath.replace('/services/', ''); 1852 const sTitles = { 1853 'career-counseling': 'Career Counseling & Profile Evaluation in Kathmandu, Nepal', 1854 'university-admissions': 'University Admissions & Scholarships for Nepali Students', 1855 'visa-documentation': 'Visa Documentation & SOP Coaching in Kathmandu, Nepal', 1856 'interview-prep': 'Visa Mock Interview Preparation | US F-1 & Australian GS Coaching', 1857 'pre-departure': 'Pre-Departure Briefing & Student Arrival Support Abroad' 1858 }; 1859 if (sTitles[sKey]) pageTitle = sTitles[sKey] + ' | Kavya Global'; 1860 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderServiceDetailPage(sKey, siteData) : renderServicesSection(); 1861 } else if (currentPath === '/test-prep' || currentPath === '/test-preparation') { 1862 pageTitle = 'PTE Academic & IELTS Preparation Nepal | Official Computerized Lab | Kavya Global'; 1863 pageDesc = 'Achieve your target score with certified Pearson and British Council master trainers in New Baneshwor, Kathmandu.'; 1864 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderTestPrepOverviewPage(siteData) : renderTestPrepSection(); 1865 } else if (currentPath === '/test-prep/pte' || currentPath === '/pte') { 1866 pageTitle = 'PTE Academic Coaching in Kathmandu | Score 65+ & 79+ Strategies | Kavya Global'; 1867 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderPtePage(siteData) : renderTestPrepSection(); 1868 } else if (currentPath === '/test-prep/ielts' || currentPath === '/ielts') { 1869 pageTitle = 'IELTS Preparation Nepal | Band 7.5+ Masterclasses in Kathmandu | Kavya Global'; 1870 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderIeltsPage(siteData) : renderTestPrepSection(); 1871 } else if (currentPath === '/mock-test' || currentPath === '/register-mock-test') { 1872 pageTitle = 'Register for Free PTE & IELTS Mock Test in Kathmandu | Kavya Global'; 1873 pageDesc = 'Take a 100% free computerized mock exam at our New Baneshwor testing center with instant score diagnostic feedback.'; 1874 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderMockTestPage(siteData, formState, formStatus) : renderTestPrepSection(); 1875 } else if (currentPath === '/contact' || currentPath === '/contact-us') { 1876 pageTitle = 'Contact Us | Education Consultancy in Kathmandu (New Baneshwor) | Kavya Global'; 1877 pageDesc = 'Visit Kavya Global Network at Aloknagar Gate, New Baneshwor, Kathmandu. Landline: +977 1-4106821, WhatsApp: +977 9709040360.'; 1878 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderContactPage(siteData, formStatus) : renderFooter(); 1879 } else if (currentPath === '/faqs' || currentPath === '/faq') { 1880 pageTitle = 'Frequently Asked Questions (FAQs) | Study Abroad from Nepal | Kavya Global'; 1881 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderFaqPage(siteData) : renderFaqSection(); 1882 } else if (currentPath === '/privacy-policy') { 1883 pageTitle = 'Privacy Policy | Kavya Global Network Nepal'; 1884 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderPrivacyPolicyPage() : ''; 1885 } else if (currentPath === '/terms' || currentPath === '/terms-of-service') { 1886 pageTitle = 'Terms of Service | Kavya Global Network Nepal'; 1887 mainContentHtml = window.KavyaPages ? window.KavyaPages.renderTermsPage() : ''; 1888 } else { 1889 // Home Page 1890 mainContentHtml = ` 1891 ${renderHeroSection()} 1892 ${renderCounterBar()} 1893 ${renderPartnersMarquee()} 1894 ${renderDirectorMessage()} 1895 ${renderServicesSection()} 1896 ${renderDestinationsSection()} 1897 ${renderVisaSuccessGallery()} 1898 ${renderTestPrepSection()} 1899 ${renderAccreditationsSection()} 1900 ${renderTestimonialsSection()} 1901 ${renderHomePartnerCtaSection()} 1902 ${renderFaqSection()} 1903 `; 1904 } 1905 1906 document.title = pageTitle; 1907 const metaDescTag = document.querySelector('meta[name="description"]'); 1908 if (metaDescTag && pageDesc) metaDescTag.setAttribute('content', pageDesc); 1909 1910 root.innerHTML = ` 1911 <div class="${wrapperClass}"> 1912 ${renderTopBar()} 1913 ${renderHeader()} 1914 <main> 1915 ${mainContentHtml} 1916 </main> 1917 ${renderFooter()} 1918 </div> 1919 ${(!isMobileMenuOpen && !isCounselingOpen && !isMockModalOpen) ? renderFloatingContacts() : ''} 1920 ${(!isCounselingOpen && !isMockModalOpen) ? renderMobileBottomBar() : ''} 1921 ${isCounselingOpen ? renderCounselingModal() : ''} 1922 ${isMockModalOpen ? renderMockTestModal() : ''} 1923 ${renderMobileDrawer()} 1924 `; 1925 1926 bindEvents(); 1927 } 1928 1929 function renderTopBar() { 1930 const currentPath = window.location.pathname.replace(/\/$/, '') || '/'; 1931 const isB2bDomain = typeof window !== 'undefined' && window.location && ( 1932 window.location.hostname.startsWith('b2b.') || 1933 new URLSearchParams(window.location.search).get('portal') === 'b2b' || 1934 new URLSearchParams(window.location.search).get('b2b') === '1' 1935 ); 1936 const isB2bActive = currentPath === '/b2b' || currentPath === '/partner-with-us' || currentPath === '/partnerships' || isB2bDomain; 1937 1938 const top = siteData.topBar || { 1939 phone: "+977 1-4106821", 1940 mobile: "+977 9709040360 / +977 9709040350", 1941 email: "[email protected]" 1942 }; 1943 1944 const social = (siteData.footer && siteData.footer.social) || { 1945 facebook: "https://www.facebook.com/officialkavyagroup", 1946 instagram: "https://www.instagram.com/officialkavyagroup/", 1947 youtube: "https://www.youtube.com/channel/UCcbNsbtVl8BLHKFFe7JWFdQ", 1948 linkedin: "https://www.linkedin.com/in/kavya-global-network-8b1807359/" 1949 }; 1950 1951 if (isB2bActive) { 1952 return ` 1953 <div class="site-topbar b2b-mode-topbar"> 1954 <div class="site-container topbar-inner"> 1955 <div class="topbar-left">
1956 <span class="topbar-item" style="color: #fc9b09; font-weight: 800;"> 1957 <i class="fa-solid fa-briefcase" style="margin-right: 6px;"></i> KAVYA GLOBAL • B2B & INSTITUTIONAL GATEWAY 1958 </span> 1959 </div> 1960 <div class="topbar-right"> 1961 <span class="topbar-item"><i class="fa-regular fa-envelope" style="color: #fc9b09; margin-right: 6px;"></i> <a href="mailto:${top.email}">${top.email}</a></span> 1962 <span class="topbar-divider">|</span> 1963 <span class="topbar-item"><i class="fa-brands fa-whatsapp" style="color: #25d366; margin-right: 6px;"></i> <a href="https://wa.me/9779709040360" target="_blank">+977 9709040360</a></span> 1964 <span class="topbar-divider">|</span> 1965 <a href="/" class="topbar-switch-student-btn" data-route="/" title="Return to Main Student Portal"> 1966 <i class="fa-solid fa-graduation-cap"></i> Student Website → 1967 </a> 1968 </div> 1969 </div> 1970 </div> 1971 `; 1972 } 1973 1974 return ` 1975 <div class="site-topbar"> 1976 <div class="site-container topbar-inner"> 1977 <div class="topbar-left"> 1978 <span class="topbar-item"><i class="fa-solid fa-phone" style="color: #fc9b09; margin-right: 6px;"></i> Landline: <a href="tel:${top.phone}">${top.phone}</a></span> 1979 <span class="topbar-divider">|</span> 1980 <span class="topbar-item"><i class="fa-brands fa-whatsapp" style="color: #25d366; margin-right: 6px;"></i> WhatsApp / Mobile: <a href="https://wa.me/9779709040360" target="_blank">+977 9709040360</a> / <a href="https://wa.me/9779709040350" target="_blank">+977 9709040350</a></span> 1981 </div> 1982 <div class="topbar-right"> 1983 <a href="/b2b" class="topbar-partner-link ${isB2bActive ? 'active' : ''}" data-route="/b2b" title="B2B Document Portal & File Dispatch (b2b.website.com)"> 1984 <i class="fa-solid fa-handshake" style="color: #fc9b09;"></i> Partner with Us <span class="topbar-b2b-badge">B2B</span> 1985 </a> 1986 <span class="topbar-divider">|</span> 1987 <span class="topbar-item"><i class="fa-regular fa-envelope" style="color: #fc9b09; margin-right: 6px;"></i> <a href="mailto:${top.email}">${top.email}</a></span> 1988 <span class="topbar-divider">|</span> 1989 <div class="topbar-social-links"> 1990 <a href="${social.facebook}" target="_blank" title="Facebook"><i class="fa-brands fa-facebook-f"></i></a> 1991 <a href="${social.instagram}" target="_blank" title="Instagram"><i class="fa-brands fa-instagram"></i></a> 1992 <a href="${social.youtube}" target="_blank" title="YouTube"><i class="fa-brands fa-youtube"></i></a> 1993 <a href="${social.linkedin}" target="_blank" title="LinkedIn"><i class="fa-brands fa-linkedin-in"></i></a> 1994 </div> 1995 </div> 1996 </div> 1997 </div> 1998 `; 1999 } 2000 2001 function renderDirectorMessage() { 2002 const d = siteData.directorMessage || { 2003 tag: "FROM THE DIRECTOR", 2004 title: "Empowering Students to Reach Their Full Potential", 2005 name: "Krishna Psd Aryal", 2006 role: "Founder & Managing Director, Kavya Global Network", 2007 quote: "Education is not just about opportunities, it's about building a better tomorrow.", 2008 description: "At Kavya Global Network, our mission has always been clear â to empower students to reach their full potential and create a future without boundaries. In today's interconnected world, education is more than a degree; it is the key to global opportunities, personal growth, and meaningful impact. We are here to guide you at every step of this journey.", 2009 image: "/uploads/managing-director-kavya.jpg" 2010 }; 2011 2012 const displayName = (d.name && d.name.trim() !== 'Managing Director') ? d.name : 'Krishna Psd Aryal'; 2013 let displayRole = d.role || 'Founder & Managing Director, Kavya Global Network'; 2014 if (!displayRole.includes('Kavya Global Network')) { 2015 displayRole = `${displayRole}, Kavya Global Network`; 2016 } 2017 2018 return ` 2019 <section id="leadership" class="director-section"> 2020 <div class="site-container"> 2021 <div class="director-card-grid"> 2022 <div class="director-img-wrapper"> 2023 <img src="${d.image}" alt="${displayName}" class="director-img" loading="lazy" decoding="async" /> 2024 </div> 2025 <div class="director-content">
2026 <span class="section-tag-pill"><i class="fa-solid fa-quote-left"></i> ${d.tag}</span> 2027 <h2 class="director-title">${d.title}</h2> 2028 <blockquote class="director-quote"> 2029 "${d.quote}" 2030 </blockquote> 2031 <p class="director-desc">${d.description}</p> 2032 <div class="director-author-info"> 2033 <div> 2034 <h4 class="director-author-name">${displayName}</h4> 2035 <p class="director-author-role">${displayRole}</p> 2036 </div> 2037 <a href="/leadership-message" data-route="/leadership-message" class="btn-director-action" style="margin-left: auto; text-decoration: none; padding: 10px 20px; font-size: 13px; font-weight: 700;"> 2038 Read Full Message <i class="fa-solid fa-arrow-right"></i> 2039 </a> 2040 </div> 2041 </div> 2042 </div> 2043 </div> 2044 </section> 2045 `; 2046 } 2047 2048 /* Dedicated About Us Page Renderer */ 2049 function renderAboutPage() { 2050 const ab = siteData.about || { 2051 tag: "WHO WE ARE", 2052 title: "About Kavya Global Network", 2053 subtitle: "Dedicated to ethical counseling, academic excellence, and student success since 2016.", 2054 storyBadge: "ESTABLISHED 2016 ⢠GOVT. REGD. ⢠MOEST IN PROCESS", 2055 storyTitle: "Empowering Next-Generation Global Scholars with Integrity & Expertise", 2056 storyP1: "Founded in 2016 in the educational hub of New Baneshwor, Kathmandu, Kavya Global Network has grown into one of Nepal's most respected and dependable overseas education consultancies. Registered under the Government of Nepal (MOEST Approval in Process), we specialize in bridging ambitious Nepalese students with world-renowned universities in the United States, Australia, Canada, United Kingdom, and Germany.", 2057 storyP2: "Over the past decade, our certified counselorsâaccredited by British Council, ICEF (#7027), and Pearsonâhave successfully guided over 10,000+ students and their families through every phase of the international education journey: from rigorous profile evaluations and high-scoring PTE/IELTS coaching to university admissions, merit scholarship maximization, and a stellar 98% visa approval track record.", 2058 storyImage: "https://images.unsplash.com/photo-1523240795612-9a054b0db644?q=80&w=800&auto=format&fit=crop", 2059 vision: "To be South Asia's most trusted, ethical, and forward-thinking overseas education pathway provider, empowering every student with accessible, high-quality global learning opportunities.", 2060 mission: "To connect ambitious Nepalese students with premier global universities through personalized mentorship, rigorous academic test preparation, transparent financial documentation, and uncompromised ethical standards.", 2061 values: [ 2062 { 2063 title: "100% Ethical & Transparent", 2064 desc: "Absolute clarity on admission chances, realistic scholarship expectations, and genuine visa documentation.", 2065 icon: "fa-scale-balanced" 2066 }, 2067 { 2068 title: "Student-First Mentorship", 2069 desc: "We align courses and institutions with each student's personal passions, career goals, and family budgets.", 2070 icon: "fa-user-graduate" 2071 }, 2072 { 2073 title: "Certified Global Counselors", 2074 desc: "Our team holds recognized British Council, ICEF (#7027), and Pearson certifications, ensuring accurate and up-to-date guidance.", 2075 icon: "fa-certificate" 2076 }, 2077 { 2078 title: "End-to-End Holistic Support", 2079 desc: "From your initial consultation and test prep to visa lodging, pre-departure briefings, and arrival assistance abroad.", 2080 icon: "fa-hands-holding-circle" 2081 } 2082 ], 2083 milestones: [ 2084 { year: "2016", title: "Inception in Kathmandu", desc: "Established in New Baneshwor as an officially registered overseas education consultancy (MOEST Approval in Process)." }, 2085 { year: "2018", title: "University Partnerships", desc: "Secured direct representations with over 25+ top-tier universities in USA & Australia." }, 2086 { year: "2020", title: "Smart PTE & IELTS Lab", desc: "Built state-of-the-art computerized testing labs with Pearson-certified instructors." }, 2087 { year: "2023", title: "8,000+ Success Milestone", desc: "Surpassed 8,000+ successful student placements with an industry-leading 98% visa rate." }, 2088 { year: "2026", title: "Global Network Expansion", desc: "Expanded offerings to Germany & UK with comprehensive scholarship and career support." } 2089 ] 2090 }; 2091 2092 const valuesHtml = (ab.values || []).map(v => ` 2093 <div class="value-card"> 2094 <div class="value-card-icon"><i class="fa-solid ${v.icon || 'fa-star'}"></i></div> 2095 <h4>${v.title}</h4> 2096 <p>${v.desc}</p> 2097 </div> 2098 `).join(''); 2099 2100 const milestonesHtml = (ab.milestones || []).map(m => ` 2101 <div class="timeline-card"> 2102 <div class="timeline-year-badge">${m.year}</div> 2103 <h4>${m.title}</h4> 2104 <p>${m.desc}</p> 2105 </div> 2106 `).join(''); 2107 2108 return ` 2109 <!-- Page Hero Banner --> 2110 <section class="page-hero-banner"> 2111 <div class="page-hero-inner"> 2112 <div class="page-breadcrumb"> 2113 <a href="/" data-route="/"><i class="fa-solid fa-house"></i> Home</a>
2114 <span class="page-breadcrumb-separator"><i class="fa-solid fa-chevron-right"></i></span> 2115 <span>Who Are We?</span> 2116 <span class="page-breadcrumb-separator"><i class="fa-solid fa-chevron-right"></i></span> 2117 <span class="current">${ab.title}</span> 2118 </div> 2119 <h1 class="page-hero-title">${ab.title}</h1> 2120 <p class="page-hero-subtitle">${ab.subtitle}</p> 2121 </div> 2122 </section> 2123 2124 <!-- Story & Overview Section --> 2125 <section class="page-section"> 2126 <div class="page-inner-container"> 2127 <div class="about-story-grid"> 2128 <div class="about-story-content"> 2129 <span class="story-badge"><i class="fa-solid fa-shield-halved"></i> ${ab.storyBadge}</span> 2130 <h2>${ab.storyTitle}</h2> 2131 <p>${ab.storyP1}</p> 2132 <p>${ab.storyP2}</p> 2133 <div class="about-highlights-pills"> 2134 <div class="about-pill-item"> 2135 <div class="about-pill-icon"><i class="fa-solid fa-award"></i></div> 2136 <div class="about-pill-text">MOEST Affiliation<br><span style="font-size:12px; color:#64748b; font-weight:normal;">Approval in Process</span></div> 2137 </div> 2138 <div class="about-pill-item"> 2139 <div class="about-pill-icon"><i class="fa-solid fa-certificate"></i></div> 2140 <div class="about-pill-text">British Council & ICEF Certified<br><span style="font-size:12px; color:#64748b; font-weight:normal;">Global Counselor Credentials (#7027)</span></div> 2141 </div> 2142 <div class="about-pill-item"> 2143 <div class="about-pill-icon"><i class="fa-solid fa-building-columns"></i></div> 2144 <div class="about-pill-text">60+ Global Partners<br><span style="font-size:12px; color:#64748b; font-weight:normal;">USA, Australia, UK, Germany</span></div> 2145 </div> 2146 <div class="about-pill-item"> 2147 <div class="about-pill-icon"><i class="fa-solid fa-passport"></i></div> 2148 <div class="about-pill-text">98% Visa Success<br><span style="font-size:12px; color:#64748b; font-weight:normal;">10,000+ Students Mentored</span></div> 2149 </div> 2150 </div> 2151 </div> 2152 <div class="about-story-image-wrap"> 2153 <img src="${ab.storyImage}" alt="Kavya Global Network Team & Campus" loading="lazy" decoding="async" /> 2154 <div class="about-floating-stat"> 2155 <div class="stat-num">10+</div> 2156 <div class="stat-desc">Years of<br>Excellence</div> 2157 </div> 2158 </div> 2159 </div> 2160 </div> 2161 </section> 2162 2163 <!-- Vision & Mission Section --> 2164 <section class="page-section bg-alt"> 2165 <div class="page-inner-container"> 2166 <div class="section-heading text-center" style="margin-bottom: 40px; text-align: center;"> 2167 <span class="section-tag-pill"><i class="fa-solid fa-compass"></i> GUIDING PRINCIPLES</span> 2168 <h2 class="section-title" style="font-size: 32px; margin-top: 10px;">Our Vision & Purpose-Driven Mission</h2> 2169 </div> 2170 <div class="vision-mission-grid"> 2171 <div class="vm-card vision-card"> 2172 <div class="vm-icon-wrap"><i class="fa-solid fa-eye"></i></div> 2173 <h3>Our Vision</h3> 2174 <p>${ab.vision}</p> 2175 </div> 2176 <div class="vm-card mission-card"> 2177 <div class="vm-icon-wrap"><i class="fa-solid fa-bullseye"></i></div> 2178 <h3>Our Mission</h3> 2179 <p>${ab.mission}</p> 2180 </div> 2181 </div> 2182 </div> 2183 </section> 2184 2185 <!-- Core Values Section --> 2186 <section class="page-section"> 2187 <div class="page-inner-container"> 2188 <div class="section-heading text-center" style="margin-bottom: 40px; text-align: center;"> 2189 <span class="section-tag-pill"><i class="fa-solid fa-heart"></i> WHAT DRIVES US</span> 2190 <h2 class="section-title" style="font-size: 32px; margin-top: 10px;">Core Values That Define Our Guidance</h2> 2191 </div> 2192 <div class="values-grid"> 2193 ${valuesHtml} 2194 </div> 2195 </div> 2196 </section> 2197 2198 <!-- Milestones Timeline Section --> 2199 <section class="page-section bg-alt"> 2200 <div class="page-inner-container"> 2201 <div class="section-heading text-center" style="margin-bottom: 40px; text-align: center;">
2202 <span class="section-tag-pill"><i class="fa-solid fa-road"></i> OUR JOURNEY</span> 2203 <h2 class="section-title" style="font-size: 32px; margin-top: 10px;">A Decade of Growth & Milestones</h2> 2204 </div> 2205 <div class="timeline-grid"> 2206 ${milestonesHtml} 2207 </div> 2208 </div> 2209 </section> 2210 2211 <!-- Bottom Universal Action Banner --> 2212 <section class="page-section" style="padding-top: 20px;"> 2213 <div class="page-inner-container"> 2214 <div class="page-cta-banner"> 2215 <div class="page-cta-left"> 2216 <h3>Start Your Global Education Journey Today</h3> 2217 <p>Meet with our certified counselors at Aloknagar Gate, New Baneshwor, Kathmandu, or schedule an online 1-on-1 strategy call to evaluate your university options and merit scholarships.</p> 2218 </div> 2219 <div class="page-cta-actions"> 2220 <button class="page-cta-btn-primary btn-trigger-counseling"><i class="fa-solid fa-calendar-check"></i> Book Free Counseling</button> 2221 <a href="https://wa.me/9779709040360" target="_blank" class="page-cta-btn-secondary"><i class="fa-brands fa-whatsapp"></i> Chat on WhatsApp</a> 2222 </div> 2223 </div> 2224 </div> 2225 </section> 2226 `; 2227 } 2228 2229 /* Dedicated Leadership Message Page Renderer */ 2230 function renderLeadershipMessagePage() { 2231 const dir = siteData.directorMessage || { 2232 tag: "FROM THE DIRECTOR", 2233 title: "Empowering Students to Reach Their Full Potential", 2234 name: "Krishna Psd Aryal", 2235 role: "Founder & Managing Director, Kavya Global Network", 2236 badge: "Founder & Managing Director", 2237 quote: "Education is not just about opportunities, it's about building a better tomorrow.", 2238 description: "At Kavya Global Network, our mission has always been clear â to empower students to reach their full potential and create a future without boundaries. In today's interconnected world, education is more than a degree; it is the key to global opportunities, personal growth, and meaningful impact. We are here to guide you at every step of this journey. We believe in building relationships based on trust and transparency, and we measure our success by the achievements of the students we serve.", 2239 image: "/uploads/managing-director-kavya.jpg", 2240 letterTitle: "From the Director â A Message to Students, Parents & Well-wishers", 2241 letterParagraphs: [], 2242 pillars: [] 2243 }; 2244 2245 const dirName = (dir.name && dir.name.trim() !== 'Managing Director') ? dir.name : 'Krishna Psd Aryal'; 2246 let dirRole = dir.role || 'Founder & Managing Director, Kavya Global Network'; 2247 if (!dirRole.includes('Kavya Global Network')) { 2248 dirRole = `${dirRole}, Kavya Global Network`; 2249 } 2250 2251 const rawParagraphs = dir.letterParagraphs && dir.letterParagraphs.length > 0 2252 ? dir.letterParagraphs 2253 : [dir.description]; 2254 2255 const paragraphsHtml = rawParagraphs.map(p => { 2256 const parts = p.split(/\n\n+/); 2257 return parts.map(part => `<p>${part.trim()}</p>`).join(''); 2258 }).join(''); 2259 2260 const pillars = dir.pillars || [ 2261 { 2262 title: "Integrity Over Volume", 2263 desc: "We never submit an application we cannot stand behind. Complete honesty in documentation and genuine academic matching.", 2264 icon: "fa-shield-halved" 2265 }, 2266 { 2267 title: "Direct Global Representation", 2268 desc: "Direct institutional partnerships ensure faster offer letters, merit scholarship priority, and smooth visa processing.", 2269 icon: "fa-university" 2270 }, 2271 { 2272 title: "Lifelong Mentorship", 2273 desc: "Our support does not end when your visa is approved. We stay connected with our student alumni across the world.", 2274 icon: "fa-user-group" 2275 } 2276 ]; 2277 2278 const pillarsHtml = pillars.map(pill => ` 2279 <div class="pillar-box"> 2280 <i class="fa-solid ${pill.icon || 'fa-check'}"></i> 2281 <h5>${pill.title}</h5> 2282 <p>${pill.desc}</p> 2283 </div> 2284 `).join(''); 2285 2286 return ` 2287 <!-- Page Hero Banner --> 2288 <section class="page-hero-banner"> 2289 <div class="page-hero-inner"> 2290 <div class="page-breadcrumb"> 2291 <a href="/" data-route="/"><i class="fa-solid fa-house"></i> Home</a>
2292 <span class="page-breadcrumb-separator"><i class="fa-solid fa-chevron-right"></i></span> 2293 <span>Who Are We?</span> 2294 <span class="page-breadcrumb-separator"><i class="fa-solid fa-chevron-right"></i></span> 2295 <span class="current">Leadership Message</span> 2296 </div> 2297 <h1 class="page-hero-title">Leadership Message</h1> 2298 <p class="page-hero-subtitle">Our vision, core values, and student-first commitment from the Founder & Managing Director.</p> 2299 </div> 2300 </section> 2301 2302 <!-- Main Leadership Grid --> 2303 <section class="page-section"> 2304 <div class="page-inner-container"> 2305 <div class="leadership-layout-grid"> 2306 2307 <!-- Sticky Sidebar: Director Profile --> 2308 <aside class="director-sticky-sidebar"> 2309 <div class="director-profile-card"> 2310 <div class="director-profile-card-img-box"> 2311 <img src="${dir.image || '/uploads/managing-director-kavya.jpg'}" alt="${dirName}" loading="lazy" decoding="async" /> 2312 <div class="director-profile-badge-overlay"> 2313 <i class="fa-solid fa-circle-check"></i> 2314 <span>${dir.badge || 'Founder & Managing Director'}</span> 2315 </div> 2316 </div> 2317 <div class="director-profile-card-body"> 2318 <h3 class="director-profile-name">${dirName}</h3> 2319 <div class="director-profile-role">${dirRole}</div> 2320 2321 <div class="director-meta-list"> 2322 <div class="director-meta-item"> 2323 <i class="fa-solid fa-location-dot"></i> 2324 <span>New Baneshwor, Kathmandu</span> 2325 </div> 2326 <div class="director-meta-item"> 2327 <i class="fa-solid fa-phone"></i> 2328 <span>+977 1-4106821</span> 2329 </div> 2330 <div class="director-meta-item"> 2331 <i class="fa-solid fa-award"></i> 2332 <span>British Council & ICEF Accredited</span> 2333 </div> 2334 <div class="director-meta-item"> 2335 <i class="fa-solid fa-stamp"></i> 2336 <span>MOEST Nepal (Approval in Process)</span> 2337 </div> 2338 </div> 2339 2340 <button class="director-btn-counsel btn-trigger-counseling"> 2341 <i class="fa-solid fa-calendar-check"></i> Schedule Executive Consultation 2342 </button> 2343 </div> 2344 </div> 2345 </aside> 2346 2347 <!-- Main Executive Letter Card --> 2348 <article class="executive-letter-card"> 2349 <span class="letter-top-tag"><i class="fa-solid fa-envelope-open-text"></i> ${dir.tag || 'EXECUTIVE SALUTATION'}</span> 2350 <h2 class="letter-title">${dir.letterTitle || dir.title}</h2> 2351 2352 <div class="executive-quote-box"> 2353 <i class="fa-solid fa-quote-right"></i> 2354 <div class="executive-quote-text">"${dir.quote}"</div> 2355 </div> 2356 2357 <div class="letter-body-paragraphs"> 2358 ${paragraphsHtml} 2359 </div> 2360 2361 <!-- Leadership Pillars --> 2362 <h4 style="font-size: 18px; font-weight: 800; color: #00332a; margin-bottom: 16px;"> 2363 <i class="fa-solid fa-feather-pointed" style="color: #fc9b09; margin-right: 8px;"></i> 2364 Our Three Uncompromising Pillars 2365 </h4> 2366 <div class="leadership-pillars-grid"> 2367 ${pillarsHtml} 2368 </div> 2369 2370 <!-- Formal Sign-Off Signature Block --> 2371 <div class="executive-signature-block"> 2372 <div class="signature-details"> 2373 <h5>${dirName}</h5> 2374 <p>${dirRole}</p> 2375 </div> 2376 <div class="signature-seal"> 2377 <i class="fa-solid fa-certificate"></i> Official Leadership 2378 </div> 2379 </div> 2380 </article> 2381 2382 </div> 2383 </div> 2384 </section> 2385 2386 <!-- Bottom Action Banner --> 2387 <section class="page-section bg-alt" style="padding-top: 40px; padding-bottom: 40px;"> 2388 <div class="page-inner-container"> 2389 <div class="page-cta-banner"> 2390 <div class="page-cta-left"> 2391 <h3>
2391Have Questions About Your Overseas Study Strategy?</h3> 2392 <p>Our senior leadership team and certified counselors are here to personally review your academic transcripts, IELTS/PTE scores, and visa eligibility.</p> 2393 </div> 2394 <div class="page-cta-actions"> 2395 <button class="page-cta-btn-primary btn-trigger-counseling"><i class="fa-solid fa-calendar-check"></i> Book Counseling Session</button> 2396 <a href="tel:+97714106821" class="page-cta-btn-secondary"><i class="fa-solid fa-phone"></i> Call +977 1-4106821</a> 2397 </div> 2398 </div> 2399 </div> 2400 </section> 2401 `; 2402 } 2403 2404 function renderVisaSuccessGallery() { 2405 const v = siteData.visaSuccess || { 2406 tag: "REAL PROOF OF SUCCESS", 2407 title: "Recent Visa Approval Gallery", 2408 items: [] 2409 }; 2410 2411 if (!v.items || v.items.length === 0) return ''; 2412 2413 // Repeat items so the track is sufficiently wide to loop smoothly 2414 let list = [...v.items]; 2415 while (list.length < 18) { 2416 list = [...list, ...v.items]; 2417 } 2418 // Duplicate for seamless 50% translation loop 2419 const doubleList = [...list, ...list]; 2420 const duration = Math.max(32, Math.round(list.length * 2.2)); 2421 2422 return ` 2423 <section id="visa-gallery" class="visa-gallery-section"> 2424 <div class="site-container" style="text-align: center;"> 2425 <div class="section-header-centered"> 2426 <span class="section-tag-pill"><i class="fa-solid fa-passport"></i> ${v.tag}</span> 2427 <h2 class="section-title-center">${v.title}</h2> 2428 <p class="section-desc-center">Congratulations to our students who recently received their student visas! Every approval is a testament to our guidance and their determination.</p> 2429 <div style="margin-top: 14px; margin-bottom: 24px;"> 2430 <a href="/visa-success" data-route="/visa-success" class="link-all-destinations" style="display: inline-flex;"> 2431 View All Visa Success Stories & Grants <i class="fa-solid fa-arrow-right"></i> 2432 </a> 2433 </div> 2434 </div> 2435 </div> 2436 2437 <!-- 1 Single Line Slowly Scrolling Container (Small Size Cards) --> 2438 <div class="visa-scroll-container"> 2439 <div class="visa-scroll-track" style="animation-duration: ${duration}s;"> 2440 ${doubleList.map((item, i) => ` 2441 <div class="visa-scroll-card" onclick="openImageModal('${item.photo}', 'Visa Grant â ${item.name} (${item.country})')" title="Click to view full size â ${item.name}"> 2442 <img 2443 src="${item.photo}" 2444 alt="Congratulations ${item.name} â ${item.country} Student Visa" 2445 class="visa-scroll-img" 2446 loading="${i < 6 ? 'eager' : 'lazy'}" 2447 decoding="async" 2448 /> 2449 <span class="visa-zoom-hint"><i class="fa-solid fa-magnifying-glass-plus"></i> View</span> 2450 </div> 2451 `).join('')} 2452 </div> 2453 </div> 2454 2455 <div class="site-container"> 2456 <div class="visa-cta-card"> 2457 <div class="visa-cta-left"> 2458 <div class="visa-cta-badge"> 2459 <span class="visa-cta-badge-dot"></span> 2460 <span>${v.items.length || 6}+ Visas Approved This Season</span> 2461 </div> 2462 <h3 class="visa-cta-heading">Ready to Be Our Next Visa Success Story?</h3> 2463 <p class="visa-cta-sub"> 2464 Join 1,500+ successful Nepalese students in USA, Australia, UK & Canada. Get direct university admissions, maximum scholarship consideration, and 1-on-1 embassy interview coaching with certified education experts. 2465 </p> 2466 <div class="visa-cta-trust-tags"> 2467 <span><i class="fa-solid fa-circle-check"></i> Govt. Regd. ⢠MOEST in Process</span> 2468 <span><i class="fa-solid fa-circle-check"></i> British Council & ICEF Accredited</span> 2469 <span><i class="fa-solid fa-circle-check"></i> 100% Free Counseling</span> 2470 </div> 2471 </div> 2472 <div class="visa-cta-right"> 2473 <button id="btn-open-counseling-visa" class="btn-visa-cta-primary"> 2474 <i class="fa-solid fa-calendar-check"></i>
2475 <span>Book Free Counseling</span> 2476 <i class="fa-solid fa-arrow-right"></i> 2477 </button> 2478 <a href="https://wa.me/9779709040360?text=Hello%20Kavya%20Global%2C%20I%20would%20like%20to%20apply%20for%20abroad%20studies." target="_blank" class="btn-visa-cta-whatsapp"> 2479 <i class="fa-brands fa-whatsapp"></i> Quick WhatsApp Inquiry 2480 </a> 2481 </div> 2482 </div> 2483 </div> 2484 </section> 2485 `; 2486 } 2487 2488 /* Header Navigation */ 2489 function renderHeader() { 2490 const h = siteData.header || { logoUrl: '/kavya-logo-official.png', counselingBtnText: 'Book Online Counseling' }; 2491 const currentPath = window.location.pathname.replace(/\/$/, '') || '/'; 2492 const isB2bDomain = typeof window !== 'undefined' && window.location && ( 2493 window.location.hostname.startsWith('b2b.') || 2494 new URLSearchParams(window.location.search).get('portal') === 'b2b' || 2495 new URLSearchParams(window.location.search).get('b2b') === '1' 2496 ); 2497 const isB2bPage = currentPath === '/b2b' || currentPath === '/partner-with-us' || currentPath === '/partnerships' || isB2bDomain; 2498 const isAboutGroup = currentPath === '/about' || currentPath === '/leadership-message' || currentPath === '/accreditations' || currentPath === '/visa-success'; 2499 const isDestGroup = currentPath.startsWith('/destinations') || currentPath.startsWith('/study-in-'); 2500 const isServicesGroup = currentPath.startsWith('/services') || currentPath === '/our-services'; 2501 const isTestPrepGroup = currentPath.startsWith('/test-prep') || currentPath === '/mock-test'; 2502 const isContactPage = currentPath === '/contact' || currentPath === '/contact-us'; 2503 const isHomePage = (currentPath === '/' || currentPath === '') && !isB2bDomain; 2504 2505 return ` 2506 <header class="header-main ${isB2bPage ? 'header-b2b-active' : ''}"> 2507 <div class="site-container header-inner-container"> 2508 <div class="header-logo-container"> 2509 <a href="${isB2bPage ? '/b2b' : '/'}" data-route="${isB2bPage ? '/b2b' : '/'}"> 2510 <img src="${h.logoUrl || '/kavya-logo-official.png'}" alt="${siteData.general.siteName}" class="header-logo-img" /> 2511 </a> 2512 ${isB2bPage ? `<span class="b2b-header-badge-tag"><i class="fa-solid fa-handshake"></i> B2B GATEWAY</span>` : ''} 2513 </div> 2514 2515 <nav class="header-nav"> 2516 ${isB2bPage ? ` 2517 <a href="/b2b#b2b-institutions" class="header-nav-link" data-route="/b2b#b2b-institutions">Partner Institutions</a> 2518 <a href="/b2b#b2b-tracks" class="header-nav-link" data-route="/b2b#b2b-tracks">Collaboration Tracks</a> 2519 <a href="/b2b#b2b-why-partner" class="header-nav-link" data-route="/b2b#b2b-why-partner">Why Choose Us</a> 2520 <a href="/b2b#partner-form-anchor" class="header-nav-link" data-route="/b2b#partner-form-anchor">Corporate Desk</a> 2521 ` : ` 2522 <a href="/" class="header-nav-link ${isHomePage ? 'active' : ''}" data-route="/">Home</a> 2523 2524 <!-- Who Are We Dropdown --> 2525 <div class="nav-dropdown"> 2526 <a href="/about" class="header-nav-link ${isAboutGroup ? 'active' : ''}" data-route="/about"> 2527 Who Are We? <i class="fa-solid fa-chevron-down nav-arrow"></i> 2528 </a> 2529 <div class="dropdown-menu-box"> 2530 <a href="/about" class="dropdown-item-link" data-route="/about"> 2531 <div class="dropdown-icon"><i class="fa-solid fa-building-columns"></i></div> 2532 <div> 2533 <div class="dropdown-title">About Kavya Network</div> 2534 <div class="dropdown-sub">Trusted education partner since 2016</div> 2535 </div> 2536 </a> 2537 <a href="/leadership-message" class="dropdown-item-link" data-route="/leadership-message"> 2538 <div class="dropdown-icon"><i class="fa-solid fa-user-tie"></i></div> 2539 <div> 2540 <div class="dropdown-title">Leadership Message</div> 2541 <div class="dropdown-sub">Vision, values & leadership commitment</div> 2542 </div> 2543 </a> 2544 <a href="/accreditations" class="dropdown-item-link" data-route="/accreditations"> 2545 <div class="dropdown-icon"><i class="fa-solid fa-award"></i></div> 2546 <div> 2547 <div class="dropdown-title">Accreditations & Licenses</div> 2548 <div class="dropdown-sub">Govt-licensed & globally certified</div> 2549 </div> 2550 </a> 2551 <a href="/visa-success" class="dropdown-item-link" data-route="/visa-success"> 2552 <div class="dropdown-icon"><i class="fa-solid fa-passport"></i></div> 2553 <div> 2554 <div class="dropdown-title">Visa Success Stories</div> 2555 <div class="dropdown-sub">Visa grants & scholarship records</div> 2556 </div> 2557 </a> 2558 <a href="/b2b" class="dropdown-item-link" data-route="/b2b"> 2559 <div class="dropdown-icon" style="background: rgba(252,155,9,0.15); color: #fc9b09;"><i class="fa-solid fa-handshake"></i></div> 2560 <div> 2561 <div class="dropdown-title">Partner with Us <span style="font-size: 10px; background: #fc9b09; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: 800; margin-left: 4px;">B2B</span></div> 2562 <div class="dropdown-sub">Universities, institutions & agents</div> 2563 </div> 2564 </a> 2565 </div> 2566 </div> 2567 2568 <!-- Destinations Dropdown (Grid-2) --> 2569 <div class="nav-dropdown"> 2570 <a href="/destinations" class="header-nav-link ${isDestGroup ? 'active' : ''}" data-route="/destinations"> 2571 Destinations <i class="fa-solid fa-chevron-down nav-arrow"></i> 2572 </a> 2573 <div class="dropdown-menu-box grid-2"> 2574 <a href="/destinations/australia" class="dropdown-item-link" data-route="/destinations/australia"> 2575 <img src="/flags/au.svg" alt="Australia Flag" class="country-flag-img" loading="lazy" decoding="async" /> 2576 <div> 2577 <div class="dropdown-title">Study in Australia</div> 2578 <div class="dropdown-sub">Top universities & post-study work</div> 2579 </div> 2580 </a> 2581 <a href="/destinations/canada" class="dropdown-item-link" data-route="/destinations/canada"> 2582 <img src="/flags/ca.svg" alt="Canada Flag" class="country-flag-img" loading="lazy" decoding="async" /> 2583 <div> 2584 <div class="dropdown-title">Study in Canada</div> 2585 <div class="dropdown-sub">DLI colleges & PGWP pathways</div> 2586 </div> 2587 </a> 2588 <a href="/destinations/uk" class="dropdown-item-link" data-route="/destinations/uk"> 2589 <img src="/flags/gb.svg" alt="UK Flag" class="country-flag-img" loading="lazy" decoding="async" /> 2590 <div> 2591 <div class="dropdown-title">Study in UK</div> 2592 <div class="dropdown-sub">Top degrees & Graduate Route</div> 2593 </div> 2594 </a> 2595 <a href="/destinations/usa" class="dropdown-item-link" data-route="/destinations/usa"> 2596 <img src="/flags/us.svg" alt="USA Flag" class="country-flag-img" loading="lazy" decoding="async" /> 2597 <div> 2598 <div class="dropdown-title">Study in USA</div> 2599 <div class="dropdown-sub">Prestige campuses & STEM OPT</div> 2600 </div> 2601 </a> 2602 <a href="/destinations/japan" class="dropdown-item-link" data-route="/destinations/japan"> 2603 <img src="/flags/jp.svg" alt="Japan Flag" class="country-flag-img" loading="lazy" decoding="async" /> 2604 <div> 2605 <div class="dropdown-title">Study in Japan</div> 2606 <div class="dropdown-sub">Language schools & career tracks</div> 2607 </div> 2608 </a> 2609 <a href="/destinations/korea" class="dropdown-item-link" data-route="/destinations/korea"> 2610 <img src="/flags/kr.svg" alt="South Korea Flag" class="country-flag-img" loading="lazy" decoding="async" /> 2611 <div> 2612 <div class="dropdown-title">Study in Korea</div> 2613 <div class="dropdown-sub">Leading tech universities & GKS</div> 2614 </div> 2615 </a> 2616 <a href="/destinations/germany" class="dropdown-item-link" data-route="/destinations/germany"> 2617 <img src="/flags/de.svg" alt="Germany Flag" class="country-flag-img" loading="lazy" decoding="async" /> 2618 <div> 2619 <div class="dropdown-title">Study in Germany</div> 2620 <div class="dropdown-sub">Tuition-free public universities</div> 2621 </div> 2622 </a> 2623 <a href="/destinations" class="dropdown-item-link view-all-link" data-route="/destinations"> 2624 <div class="dropdown-icon"><i class="fa-solid fa-arrow-right"></i></div> 2625 <div> 2626 <div class="dropdown-title">View All Destinations</div> 2627 <div class="dropdown-sub">Explore all 7 study countries</div> 2628 </div> 2629 </a> 2630 </div> 2631 </div> 2632 2633 <!-- Services Dropdown --> 2634 <div class="nav-dropdown"> 2635 <a href="/services" class="header-nav-link ${isServicesGroup ? 'active' : ''}" data-route="/services"> 2636 Services <i class="fa-solid fa-chevron-down nav-arrow"></i> 2637 </a> 2638 <div class="dropdown-menu-box"> 2639 <a href="/services" class="dropdown-item-link" data-route="/services"> 2640 <div class="dropdown-icon"><i class="fa-solid fa-layer-group"></i></div> 2641 <div> 2642 <div class="dropdown-title">All Services Overview</div> 2643 <div class="dropdown-sub">Complete counseling & visa support</div> 2644 </div> 2645 </a> 2646 <a href="/services/career-counseling" class="dropdown-item-link" data-route="/services/career-counseling"> 2647 <div class="dropdown-icon"><i class="fa-solid fa-comments"></i></div> 2648 <div> 2649 <div class="dropdown-title">Career Counseling</div> 2650 <div class="dropdown-sub">Profile assessment & career mapping</div> 2651 </div> 2652 </a> 2653 <a href="/services/university-admissions" class="dropdown-item-link" data-route="/services/university-admissions"> 2654 <div class="dropdown-icon"><i class="fa-solid fa-building-columns"></i></div> 2655 <div> 2656 <div class="dropdown-title">University Admissions</div> 2657 <div class="dropdown-sub">Direct applications & scholarships</div> 2658 </div> 2659 </a> 2660 <a href="/services/visa-documentation" class="dropdown-item-link" data-route="/services/visa-documentation"> 2661 <div class="dropdown-icon"><i class="fa-solid fa-file-shield"></i></div> 2662 <div> 2663 <div class="dropdown-title">Visa Documentation & SOP</div> 2664 <div class="dropdown-sub">Documentation audit & compliance</div> 2665 </div> 2666 </a> 2667 <a href="/services/interview-prep" class="dropdown-item-link" data-route="/services/interview-prep"> 2668 <div class="dropdown-icon"><i class="fa-solid fa-user-tie"></i></div> 2669 <div> 2670 <div class="dropdown-title">Visa Mock Interview Prep</div> 2671 <div class="dropdown-sub">Simulated 1-on-1 consular practice</div> 2672 </div> 2673 </a> 2674 <a href="/services/pre-departure" class="dropdown-item-link" data-route="/services/pre-departure"> 2675 <div class="dropdown-icon"><i class="fa-solid fa-plane-departure"></i></div> 2676 <div> 2677 <div class="dropdown-title">Pre-Departure & Arrival</div> 2678 <div class="dropdown-sub">Pre-travel orientation & support</div> 2679 </div> 2680 </a> 2681 </div> 2682 </div> 2683 2684 <!-- Test Prep Dropdown --> 2685 <div class="nav-dropdown"> 2686 <a href="/test-prep" class="header-nav-link ${isTestPrepGroup ? 'active' : ''}" data-route="/test-prep"> 2687 Test Prep <i class="fa-solid fa-chevron-down nav-arrow"></i> 2688 </a> 2689 <div class="dropdown-menu-box"> 2690 <a href="/test-prep" class="dropdown-item-link" data-route="/test-prep"> 2691 <div class="dropdown-icon"><i class="fa-solid fa-desktop"></i></div> 2692 <div> 2693 <div class="dropdown-title">Test Prep Overview</div> 2694 <div class="dropdown-sub">Official testing labs & instructors</div> 2695 </div> 2696 </a> 2697 <a href="/test-prep/pte" class="dropdown-item-link" data-route="/test-prep/pte"> 2698 <div class="dropdown-icon"><i class="fa-solid fa-keyboard"></i></div> 2699 <div> 2700 <div class="dropdown-title">PTE Academic Coaching</div> 2701 <div class="dropdown-sub">Pearson-certified coaching & mock tests</div> 2702 </div> 2703 </a> 2704 <a href="/test-prep/ielts" class="dropdown-item-link" data-route="/test-prep/ielts"> 2705 <div class="dropdown-icon"><i class="fa-solid fa-book-open"></i></div> 2706 <div> 2707 <div class="dropdown-title">IELTS Preparation Nepal</div> 2708 <div class="dropdown-sub">Certified training & speaking practice</div> 2709 </div> 2710 </a> 2711 <a href="/mock-test" class="dropdown-item-link" data-route="/mock-test"> 2712 <div class="dropdown-icon" style="color: #fc9b09; background: rgba(252, 155, 9, 0.12);"><i class="fa-solid fa-calendar-check"></i></div> 2713 <div> 2714 <div class="dropdown-title">Book Free Mock Test</div> 2715 <div class="dropdown-sub">Free diagnostic test with feedback</div> 2716 </div> 2717 </a> 2718 </div> 2719 </div> 2720 2721 <a href="/contact" class="header-nav-link ${isContactPage ? 'active' : ''}" data-route="/contact">Contact Us</a> 2722 `} 2723 </nav> 2724 2725 <div class="header-right-actions"> 2726 ${isB2bPage ? ` 2727 <a href="/" data-route="/" class="btn-switch-main-site" title="Return to Main Student Portal"> 2728 <i class="fa-solid fa-graduation-cap"></i> <span>Student Website</span> 2729 </a> 2730 ` : ` 2731 <button id="btn-open-counseling" class="btn-primary-header" title="Schedule Online WhatsApp Video or In-Person Counseling"> 2732 <i class="fa-solid fa-headset"></i>
2733 <span>${h.counselingBtnText || 'Book Free Counseling'}</span> 2734 </button> 2735 `} 2736 <button id="btn-mobile-menu-toggle" class="btn-mobile-menu-toggle" aria-label="Toggle navigation menu" title="Open Menu"> 2737 <i class="fa-solid ${isMobileMenuOpen ? 'fa-xmark' : 'fa-bars'}"></i> 2738 </button> 2739 </div> 2740 </div> 2741 </header> 2742 `; 2743 } 2744 2745 /* Dedicated Full-Screen Professional Admin Login Page */ 2746 function renderAdminLoginPage() { 2747 return ` 2748 <div class="admin-login-fullscreen"> 2749 <div class="admin-login-card-pro"> 2750 <div class="admin-login-header"> 2751 <img src="/kavya-logo-official.png" alt="Kavya Global Logo" style="height: 48px; margin-bottom: 14px;" /> 2752 <h3>CMS Admin Portal Login</h3> 2753 <p>Enter your administrator password to edit website content and manage leads.</p> 2754 </div> 2755 <form id="admin-login-form"> 2756 ${loginErrorMsg ? `<div class="admin-login-error"><i class="fa-solid fa-circle-exclamation"></i> ${loginErrorMsg}</div>` : ''} 2757 <div class="admin-form-group"> 2758 <label for="admin-pass-input">Admin Password</label> 2759 <input type="password" id="admin-pass-input" placeholder="Enter password (default: kavya2026)" required autofocus /> 2760 </div> 2761 <button type="submit" class="btn-submit-login" style="width: 100%; height: 48px; font-size: 14px; font-weight: 800; margin-top: 10px;"> 2762 <i class="fa-solid fa-key"></i> UNLOCK CMS PORTAL 2763 </button> 2764 <button type="button" id="btn-view-live-site-login" class="btn-cancel-admin" style="width: 100%; margin-top: 12px; height: 44px;"> 2765 â Back to Live Website 2766 </button> 2767 </form> 2768 </div> 2769 </div> 2770 `; 2771 } 2772 2773 /* Accreditations & Certifications Section */ 2774 /* Accreditations & Official Recognition Section */ 2775 function renderAccreditationsSection() { 2776 if (!siteData.accreditations) return ''; 2777 const { tag, title, description, items } = siteData.accreditations; 2778 2779 return ` 2780 <section id="accreditations" class="accreditations-section-pro"> 2781 <div class="site-container"> 2782 <div class="accred-banner-container"> 2783 <div class="accred-header"> 2784 <span class="accred-tag-gold"> 2785 <i class="fa-solid fa-shield-halved"></i> ${tag || 'OFFICIAL RECOGNITION & TRUST'} 2786 </span> 2787 <h2 class="accred-main-title">${title || 'Govt. Approved & Globally Certified Consultancy'}</h2> 2788 <p class="accred-sub-desc">${description || 'Kavya Global Network is fully licensed by government ministries and certified by international education bodies.'}</p> 2789 <div style="margin-top: 14px;"> 2790 <a href="/accreditations" data-route="/accreditations" class="link-all-destinations" style="display: inline-flex; background: rgba(255,255,255,0.15); color: #fff;"> 2791 View All Government Licenses & Certificates <i class="fa-solid fa-arrow-right"></i> 2792 </a> 2793 </div> 2794 </div> 2795 2796 <div class="accred-grid-pro"> 2797 ${items.map((a, i) => ` 2798 <div class="accred-card-pro"> 2799 <div class="accred-seal-top"> 2800 <i class="fa-solid fa-circle-check"></i> ${a.badge || 'VERIFIED'} 2801 </div> 2802 <div class="accred-icon-ring"> 2803 ${a.image ? `<img src="${a.image}" alt="${a.title}" style="max-height: 52px; max-width: 52px; object-fit: contain; border-radius: 6px;" />` : `<i class="fa-solid ${a.icon || 'fa-award'}"></i>`} 2804 </div> 2805 <h4 class="accred-card-title">${a.title}</h4> 2806 <p class="accred-card-sub">${a.subtitle}</p> 2807 <div class="accred-card-footer"> 2808 <span><i class="fa-solid fa-circle-dot" style="color: #25d366;"></i> Active License</span> 2809 </div> 2810 </div> 2811 `).join('')} 2812 </div> 2813 2814 <!-- Bottom Trust Assurance Strip --> 2815 <div class="accred-trust-strip"> 2816 <div class="trust-strip-item"> 2817 <i class="fa-solid fa-building-shield"></i> 2818 <div> 2819 <strong>MOEST Affiliation</strong>
2820 <span>Approval in Process</span> 2821 </div> 2822 </div> 2823 <div class="trust-strip-divider"></div> 2824 <div class="trust-strip-item"> 2825 <i class="fa-solid fa-graduation-cap"></i> 2826 <div> 2827 <strong>British Council</strong> 2828 <span>Certified UK Partner</span> 2829 </div> 2830 </div> 2831 <div class="trust-strip-divider"></div> 2832 <div class="trust-strip-item"> 2833 <i class="fa-solid fa-certificate"></i> 2834 <div> 2835 <strong>ICEF Accredited</strong> 2836 <span>Trusted Agency #7027</span> 2837 </div> 2838 </div> 2839 </div> 2840 </div> 2841 </div> 2842 </section> 2843 `; 2844 } 2845 2846 /* Generate HTML for 1 single line slowly scrolling track */ 2847 function getScrollTrackHtml(filterDest = 'all') { 2848 if (!siteData.partners || !siteData.partners.logos) return ''; 2849 let filtered = siteData.partners.logos; 2850 if (filterDest && filterDest !== 'all') { 2851 filtered = siteData.partners.logos.filter(p => (p.location || '').toLowerCase() === filterDest.toLowerCase()); 2852 } else { 2853 // Interleave/balance across all destinations so all countries are prominently featured 2854 const byCountry = {}; 2855 siteData.partners.logos.forEach(item => { 2856 const loc = item.location || 'Other'; 2857 if (!byCountry[loc]) byCountry[loc] = []; 2858 byCountry[loc].push(item); 2859 }); 2860 const order = ['Australia', 'USA', 'UK', 'Canada', 'Europe']; 2861 const countries = order.filter(c => byCountry[c]); 2862 const balanced = []; 2863 let added = true; 2864 let round = 0; 2865 while (added) { 2866 added = false; 2867 for (const c of countries) { 2868 if (round < byCountry[c].length) { 2869 balanced.push(byCountry[c][round]); 2870 added = true; 2871 } 2872 } 2873 round++; 2874 } 2875 filtered = balanced; 2876 } 2877 if (filtered.length === 0) return '<div style="padding: 20px; text-align: center; color: #666;">No institutions found for this destination.</div>'; 2878 2879 // Keep track optimal so browser GPU hardware accelerates the animation smoothly 2880 let list = [...filtered]; 2881 while (list.length < 16) { 2882 list = [...list, ...filtered]; 2883 } 2884 // Duplicate for seamless 50% translation loop 2885 const doubleList = [...list, ...list]; 2886 const duration = Math.min(100, Math.max(35, Math.round(list.length * 1.5))); 2887 2888 return ` 2889 <div class="partner-scroll-track" style="animation-duration: ${duration}s;"> 2890 ${doubleList.map(p => { 2891 const siteUrl = p.website || p.url || '#'; 2892 return ` 2893 <a href="${siteUrl}" ${siteUrl !== '#' ? 'target="_blank" rel="noopener noreferrer"' : ''} class="partner-scroll-card" title="Visit Official Website: ${p.name} (${p.location || 'Global'})"> 2894 <div class="partner-scroll-img-wrap"> 2895 ${p.img ? ` 2896 <img src="${p.img}" alt="${p.name}" class="partner-scroll-img" loading="lazy" decoding="async" onerror="this.style.display='none'; var s=this.nextElementSibling; if(s) s.style.display='flex';" /> 2897 <span class="partner-fallback-text" style="display:none;"><i class="fa-solid fa-graduation-cap"></i> ${p.name}</span> 2898 ` : ` 2899 <span class="partner-fallback-text"><i class="fa-solid fa-graduation-cap"></i> ${p.name}</span> 2900 `} 2901 </div> 2902 <div class="partner-scroll-name" title="${p.name}">${p.name}</div> 2903 <div class="partner-card-action-row"> 2904 <span class="partner-scroll-badge"><i class="fa-solid fa-circle-check"></i> ${p.location || 'Direct Partner'}</span> 2905 <span class="partner-visit-link"><i class="fa-solid fa-arrow-up-right-from-square"></i> Visit Site</span> 2906 </div> 2907 </a> 2908 `; 2909 }).join('')} 2910 </div> 2911 `; 2912 } 2913 2914 2915 /* University Partners Logo Showcase (1 Single Line Slowly Scrolling) */ 2916 function renderPartnersMarquee() { 2917 if (!siteData.partners || !siteData.partners.logos) return ''; 2918 const { logos } = siteData.partners; 2919 2920 const ausCount = logos.filter(p => (p.location || '').toLowerCase() === 'australia').length; 2921 const usaCount = logos.filter(p => (p.location || '').toLowerCase() === 'usa').length; 2922 const ukCount = logos.filter(p => (p.location || '').toLowerCase() === 'uk').length; 2923 const eurCount = logos.filter(p => (p.location || '').toLowerCase() === 'europe').length; 2924 const canCount = logos.filter(p => (p.location || '').toLowerCase() === 'canada').length; 2925 2926 return ` 2927 <section id="represented-institutions" class="partners-marquee-section"> 2928 <div class="site-container" style="text-align: center; margin-bottom: 24px;">
2929 <span class="section-tag-pill"><i class="fa-solid fa-graduation-cap"></i> OFFICIAL GLOBAL PARTNERSHIPS</span> 2930 <h2 class="section-title-center" style="margin-top: 8px; font-size: 32px; font-weight: 800; color: #00332a;">Universities & Colleges We Represent</h2> 2931 <p class="section-desc-center" style="max-width: 720px; margin: 0 auto 18px; color: #556965; font-size: 15px;">Directly authorized representing institutions across Australia, USA, UK, Canada, and Europe.</p> 2932 2933 <!-- Interactive Destination Filter Tabs --> 2934 <div class="partner-dest-tabs"> 2935 <button class="partner-dest-tab-btn active" data-dest="all"> 2936 <i class="fa-solid fa-globe"></i> All Destinations (${logos.length}) 2937 </button> 2938 <button class="partner-dest-tab-btn" data-dest="Australia"> 2939 ð¦ðº Australia (${ausCount}) 2940 </button> 2941 <button class="partner-dest-tab-btn" data-dest="USA"> 2942 ðºð¸ USA (${usaCount}) 2943 </button> 2944 <button class="partner-dest-tab-btn" data-dest="UK"> 2945 ð¬ð§ UK (${ukCount}) 2946 </button> 2947 <button class="partner-dest-tab-btn" data-dest="Europe"> 2948 ðªðº Europe (${eurCount}) 2949 </button> 2950 <button class="partner-dest-tab-btn" data-dest="Canada"> 2951 ð¨ð¦ Canada (${canCount}) 2952 </button> 2953 </div> 2954 </div> 2955 2956 <!-- 1 Single Line Slowly Scrolling Container --> 2957 <div id="partner-scroll-container" class="partner-scroll-container"> 2958 ${getScrollTrackHtml('all')} 2959 </div> 2960 </section> 2961 `; 2962 } 2963 2964 /* Institutions We Represent Section */ 2965 function renderRepresentedInstitutions() { 2966 const data = siteData.representedInstitutions || { 2967 tag: "OFFICIAL GLOBAL PARTNERSHIPS", 2968 title: "Institutions We Represent", 2969 description: "Kavya Global Network is directly authorized to represent leading universities, institutes of technology, and higher education colleges across Australia, Europe, UK, Canada, and USA.", 2970 slides: [] 2971 }; 2972 2973 if (!data.slides || data.slides.length === 0) return ''; 2974 2975 return ` 2976 <section id="represented-institutions" class="represented-section"> 2977 <div class="site-container"> 2978 <div class="section-header-center"> 2979 <div class="section-tag-center"><i class="fa-solid fa-building-columns"></i> ${data.tag}</div> 2980 <h2 class="section-title-center">${data.title}</h2> 2981 <p class="section-desc-center">${data.description}</p> 2982 </div> 2983 2984 <!-- Country Filter Bar --> 2985 <div class="inst-filter-tabs"> 2986 <button class="inst-tab-btn active" data-filter="all"> 2987 <i class="fa-solid fa-globe"></i> All Destinations 2988 </button> 2989 ${data.slides.map(s => ` 2990 <button class="inst-tab-btn" data-filter="${s.id}"> 2991 <span>${s.flag}</span> ${s.country} 2992 </button> 2993 `).join('')} 2994 </div> 2995 2996 <!-- Slides & List Showcase --> 2997 <div class="inst-showcase-grid"> 2998 ${data.slides.map(s => ` 2999 <div class="inst-card-slide" data-category="${s.id}"> 3000 <div class="inst-slide-header"> 3001 <div class="inst-header-left"> 3002 <span class="inst-flag-badge">${s.flag} ${s.country}</span> 3003 <h3>${s.title}</h3> 3004 </div> 3005 <div class="inst-count-pill"> 3006 <i class="fa-solid fa-circle-check"></i> ${s.count} 3007 </div> 3008 </div> 3009 3010 <div class="inst-slide-img-wrapper" onclick="openImageModal('${s.image}', '${s.title}')"> 3011 <img src="${s.image}" alt="${s.title}" class="inst-slide-image" loading="lazy" decoding="async" onerror="this.onerror=null; this.parentElement.style.display='none';" /> 3012 <div class="inst-image-hover-overlay"> 3013 <button class="btn-expand-slide"> 3014 <i class="fa-solid fa-magnifying-glass-plus"></i> Click to Zoom Full Image 3015 </button> 3016 </div> 3017 </div> 3018 3019 <div class="inst-unis-list-box"> 3020 <div class="inst-unis-heading"> 3021 <i class="fa-solid fa-graduation-cap"></i> Directly Represented Universities & Colleges: 3022 </div> 3023 <div class="inst-chips-flex"> 3024 ${s.unis ? s.unis.map(u =>
3024 `<span class="inst-chip-pill"><i class="fa-solid fa-check"></i> ${u}</span>`).join('') : ''} 3025 </div> 3026 </div> 3027 </div> 3028 `).join('')} 3029 </div> 3030 </div> 3031 </section> 3032 `; 3033 } 3034 3035 /* Hero Section Image-Only Slider Layout (Superfast High-Performance) */ 3036 function renderHeroSection() { 3037 const defaultSlides = [ 3038 { 3039 image: '/uploads/2026/01/website-slider-scaled.webp', 3040 imageMobile: '/uploads/2026/01/website-slider-scaled-mobile.webp', 3041 fallback: '/uploads/2026/01/website-slider-scaled.png', 3042 alt: 'Welcome to Kavya Global Network â Where Dreams Meet Destinations' 3043 }, 3044 { 3045 image: '/uploads/2025/04/website-slider-7.webp', 3046 imageMobile: '/uploads/2025/04/website-slider-7-mobile.webp', 3047 fallback: '/uploads/2025/04/website-slider-7.png', 3048 alt: 'Best Education Consultancy in Nepal' 3049 }, 3050 { 3051 image: '/uploads/2025/04/website-slider-5.webp', 3052 imageMobile: '/uploads/2025/04/website-slider-5-mobile.webp', 3053 fallback: '/uploads/2025/04/website-slider-5.png', 3054 alt: 'PTE Academic and IELTS Preparation Classes' 3055 }, 3056 { 3057 image: '/uploads/2025/04/kavya-10th-anniversary-slider.webp', 3058 imageMobile: '/uploads/2025/04/kavya-10th-anniversary-slider-mobile.webp', 3059 fallback: '/uploads/2025/04/kavya-10th-anniversary-slider.jpg', 3060 alt: 'Kavya Global Network â 10th Anniversary' 3061 } 3062 ]; 3063 3064 const rawSlides = (siteData.hero && siteData.hero.slides && siteData.hero.slides.length > 0) 3065 ? siteData.hero.slides 3066 : defaultSlides; 3067 3068 const slides = rawSlides.map(s => { 3069 const orig = s.image || ''; 3070 const webp = s.imageWebp || (orig.endsWith('.webp') ? orig : orig.replace(/\.(png|jpe?g)$/i, '.webp')); 3071 const mobile = s.imageMobile || (orig.includes('-mobile.webp') ? orig : webp.replace(/\.webp$/i, '-mobile.webp')); 3072 return { 3073 image: webp, 3074 imageMobile: mobile, 3075 fallback: s.fallback || orig, 3076 alt: s.alt || 'Kavya Global Network Slider' 3077 }; 3078 }); 3079 3080 setTimeout(() => { 3081 initHeroSlider(); 3082 }, 20); 3083 3084 return ` 3085 <section class="hero-slider-section"> 3086 <div class="hero-carousel-wrapper"> 3087 <div class="hero-carousel-track" id="hero-carousel-track"> 3088 ${slides.map((slide, idx) => ` 3089 <div class="hero-carousel-slide ${idx === 0 ? 'active' : ''}" data-index="${idx}"> 3090 <picture> 3091 <source media="(max-width: 768px)" srcset="${slide.imageMobile}" type="image/webp"> 3092 <source srcset="${slide.image}" type="image/webp"> 3093 <img src="${slide.fallback || slide.image}" alt="${slide.alt}" class="hero-slide-img" fetchpriority="${idx === 0 ? 'high' : 'auto'}" loading="${idx === 0 ? 'eager' : 'lazy'}" decoding="async" /> 3094 </picture> 3095 </div> 3096 `).join('')} 3097 </div> 3098 <button class="hero-nav-arrow hero-nav-prev" onclick="window.KavyaChangeHeroSlide(-1)" aria-label="Previous Slide"> 3099 <i class="fa-solid fa-chevron-left"></i> 3100 </button> 3101 <button class="hero-nav-arrow hero-nav-next" onclick="window.KavyaChangeHeroSlide(1)" aria-label="Next Slide"> 3102 <i class="fa-solid fa-chevron-right"></i> 3103 </button> 3104 <div class="hero-dots-container"> 3105 ${slides.map((_, idx) => ` 3106 <button class="hero-dot-indicator ${idx === 0 ? 'active' : ''}" onclick="window.KavyaGoToHeroSlide(${idx})" aria-label="Go to slide ${idx + 1}"></button> 3107 `).join('')} 3108 </div> 3109 </div> 3110 </section> 3111 `; 3112 } 3113 3114 /* Quick Discover Destination & Service Chips Strip (Removed) */ 3115 function renderQuickDiscoverStrip() { 3116 return ''; 3117 } 3118 3119 /* Stats Counter Bar */ 3120 function renderCounterBar() { 3121 const counters = siteData.counters; 3122 return ` 3123 <section class="stats-bar-section"> 3124 <div class="site-container"> 3125 <div class="stats-grid"> 3126 ${counters.map(c => ` 3127 <div class="stat-card"> 3128 <div class="stat-icon"><i class="fa-solid ${c.icon}"></i></div> 3129 <div class="stat-number">${c.number}</div> 3130 <div class="stat-label">${c.label}</div> 3131 </div> 3132 `).join('')} 3133 </div> 3134 </div> 3135 </section> 3136 `; 3137 } 3138 3139 /* Services Section */
3140 function renderServicesSection() { 3141 const { tag, title, description, items } = siteData.services; 3142 return ` 3143 <section id="services" class="services-section"> 3144 <div class="site-container"> 3145 <div class="section-header-center"> 3146 <div class="section-tag-center">${tag}</div> 3147 <h2 class="section-title-center">${title}</h2> 3148 <p class="section-desc-center">${description}</p> 3149 </div> 3150 <div class="services-grid-4"> 3151 ${items.map(s => { 3152 const serviceRouteMap = { 3153 's1': '/services/career-counseling', 3154 's2': '/services/university-admissions', 3155 's3': '/services/visa-documentation', 3156 's4': '/services/interview-prep' 3157 }; 3158 const routeUrl = serviceRouteMap[s.id] || '/services'; 3159 return ` 3160 <a href="${routeUrl}" data-route="${routeUrl}" class="service-card-modern" style="text-decoration: none; color: inherit; display: block;"> 3161 <div class="service-circle-icon"><i class="fa-solid ${s.icon}"></i></div> 3162 <h4>${s.title}</h4> 3163 <p>${s.description}</p> 3164 <span class="service-learn-more" style="display: inline-flex; align-items: center; gap: 6px; color: var(--kgn-primary); font-weight: 700; font-size: 13px; margin-top: 14px;"> 3165 Learn More <i class="fa-solid fa-arrow-right" style="font-size: 11px;"></i> 3166 </span> 3167 </a> 3168 `; 3169 }).join('')} 3170 </div> 3171 </div> 3172 </section> 3173 `; 3174 } 3175 3176 /* Destinations Bento Grid */ 3177 function renderDestinationsSection() { 3178 const { tag, title, items = [] } = siteData.destinations || {}; 3179 3180 return ` 3181 <section id="destinations" class="destinations-section"> 3182 <div class="site-container"> 3183 <div class="destinations-header-row"> 3184 <div> 3185 <div class="section-tag-center" style="text-align: left;">${tag || 'GLOBAL STUDY DESTINATIONS'}</div> 3186 <h2 class="section-title-center" style="text-align: left; margin: 0;">${title || 'Top Countries for Your International Degree'}</h2> 3187 </div> 3188 <a href="/destinations" data-route="/destinations" class="link-all-destinations"> 3189 View All Destinations <i class="fa-solid fa-arrow-right"></i> 3190 </a> 3191 </div> 3192 3193 <div class="bento-grid"> 3194 ${items.map(d => { 3195 const routeUrl = `/destinations/${d.id}`; 3196 return ` 3197 <a href="${routeUrl}" data-route="${routeUrl}" class="bento-card"> 3198 <img src="${d.image}" alt="${d.title}" loading="lazy" decoding="async" /> 3199 <div class="bento-top-badges"> 3200 <span class="bento-flag-pill"><i class="fa-solid fa-location-dot" style="color: #f9981b; margin-right: 5px;"></i> ${d.title}</span> 3201 ${d.badge ? `<span class="bento-intake-badge">${d.badge}</span>` : ''} 3202 ${d.subBadge ? `<span class="bento-intake-badge" style="background: var(--kgn-primary);">${d.subBadge}</span>` : ''} 3203 </div> 3204 <div class="bento-overlay"> 3205 <h3>${d.title}</h3> 3206 <div class="bento-arrow-circle"><i class="fa-solid fa-arrow-right"></i></div> 3207 </div> 3208 </a> 3209 `; 3210 }).join('')} 3211 3212 <a href="/destinations" data-route="/destinations" class="bento-card-more" style="text-decoration: none; color: #ffffff !important; display: flex; flex-direction: column; align-items: center; justify-content: center; cursor: pointer;"> 3213 <i class="fa-solid fa-globe" style="color: #fc9b09;"></i> 3214 <h3 style="color: #ffffff !important;">More Destinations</h3> 3215 <p style="color: rgba(255, 255, 255, 0.92) !important;">New Zealand, Japan, Korea, Denmark & many more</p> 3216 </a> 3217 </div> 3218 </div> 3219 </section> 3220 `; 3221 } 3222 3223 /* Test Prep & Book Mock Test Form */ 3224 function renderTestPrepSection() { 3225 const { tag, title, description, features, formTitle, formSub } = siteData.testPrep; 3226 return ` 3227 <section id="test-prep" class="test-prep-section"> 3228 <div class="test-prep-inner-grid"> 3229 <div class="prep-left"> 3230 <div class="section-tag-center" style="text-align: left;">${tag}</div> 3231 <h2 class="section-title-center" style="text-align: left;">${title}</h2> 3232 <p class="section-desc-center" style="text-align: left;">${description}</p> 3233 3234 <div class="prep-features-grid"> 3235 ${features.map(f => `
3236 <div class="prep-feature-card"> 3237 <div class="prep-icon"><i class="fa-solid ${f.icon}"></i></div> 3238 <div class="prep-info"> 3239 <h5>${f.title}</h5> 3240 <span>${f.sub}</span> 3241 </div> 3242 </div> 3243 `).join('')} 3244 </div> 3245 3246 <div style="display: flex; gap: 14px; margin-top: 24px; flex-wrap: wrap;"> 3247 <a href="/test-prep/pte" data-route="/test-prep/pte" class="btn-primary-header" style="font-size: 13px; padding: 10px 20px; text-decoration: none;"> 3248 <i class="fa-solid fa-laptop-code"></i> PTE Academic Coaching 3249 </a> 3250 <a href="/test-prep/ielts" data-route="/test-prep/ielts" class="btn-director-action" style="font-size: 13px; padding: 10px 20px; text-decoration: none;"> 3251 <i class="fa-solid fa-pen-nib"></i> IELTS Masterclasses 3252 </a> 3253 </div> 3254 </div> 3255 3256 <div id="register-form" class="mock-form-dark"> 3257 <div class="mock-form-header"> 3258 <h3>${formTitle}</h3> 3259 <p>${formSub}</p> 3260 </div> 3261 3262 ${formStatus ? ` 3263 <div style="padding: 10px; background: rgba(255,255,255,0.2); border-radius: 6px; font-size: 13px; margin-bottom: 15px;">${formStatus.text}</div> 3264 ` : ''} 3265 3266 <form id="mock-booking-form"> 3267 <div class="form-grid-2"> 3268 <div class="form-field-group"> 3269 <label>Full Name</label> 3270 <input type="text" id="field-name" placeholder="Enter your name" value="${formState.name}" required /> 3271 </div> 3272 <div class="form-field-group"> 3273 <label>Test Type</label> 3274 <select id="field-testtype"> 3275 <option value="IELTS Academic">IELTS Academic</option> 3276 <option value="PTE Academic" selected>PTE Academic</option> 3277 <option value="TOEFL">TOEFL</option> 3278 <option value="SAT">SAT</option> 3279 </select> 3280 </div> 3281 </div> 3282 3283 <div class="form-grid-2"> 3284 <div class="form-field-group"> 3285 <label>Date</label> 3286 <input type="date" id="field-date" value="${formState.date}" /> 3287 </div> 3288 <div class="form-field-group"> 3289 <label>Time Slot</label> 3290 <select id="field-timeslot"> 3291 <option value="08:00 AM - 11:00 AM">08:00 AM - 11:00 AM</option> 3292 <option value="11:30 AM - 02:30 PM">11:30 AM - 02:30 PM</option> 3293 <option value="03:00 PM - 06:00 PM">03:00 PM - 06:00 PM</option> 3294 </select> 3295 </div> 3296 </div> 3297 3298 <div class="form-grid-2"> 3299 <div class="form-field-group"> 3300 <label>Email Address *</label> 3301 <input type="email" id="field-email" placeholder="Enter your email" value="${formState.email}" required /> 3302 </div> 3303 <div class="form-field-group"> 3304 <label>Mobile / WhatsApp *</label> 3305 <input type="tel" id="field-phone" placeholder="e.g. 98XXXXXXXX" value="${formState.phone}" required /> 3306 </div> 3307 </div> 3308 3309 <button type="submit" class="btn-confirm-booking">CONFIRM BOOKING</button> 3310 </form> 3311 </div> 3312 </div> 3313 </section> 3314 `; 3315 } 3316 3317 /* Testimonials â Google Reviews Scrolling Showcase */ 3318 function renderTestimonialsSection() { 3319 const t = siteData.testimonials || { tag: "REAL STUDENT EXPERIENCES", reviews: [] }; 3320 const reviews = t.reviews || []; 3321 if (reviews.length === 0) return ''; 3322 3323 // Repeat items so the track is sufficiently wide to loop smoothly 3324 let list = [...reviews]; 3325 while (list.length < 16) { 3326 list = [...list, ...reviews]; 3327 } 3328 const doubleList = [...list, ...list]; 3329 const duration = Math.max(45, Math.round(list.length * 3.4)); 3330 3331 return ` 3332 <section id="testimonials" class="testimonials-section"> 3333 <div class="site-container" style="text-align: center;">
3334 <span class="section-tag-pill"><i class="fa-solid fa-star" style="color: #fc9b09;"></i> ${t.tag}</span> 3335 <h2 class="section-title-center">${t.title || 'Student Success Stories'}</h2> 3336 <p class="section-desc-center" style="max-width: 700px; margin: 0 auto 24px; color: #556965; font-size: 15px;"> 3337 ${t.subtitle || 'Verified reviews from students who achieved their overseas education goals with Kavya Global Network.'} 3338 </p> 3339 3340 <!-- Google Business Profile Rating Summary Header Badge --> 3341 <div class="google-rating-banner"> 3342 <div class="google-rating-logo"> 3343 <svg width="28" height="28" viewBox="0 0 24 24"><path fill="#4285F4" d="M23.745 12.27c0-.7-.06-1.4-.19-2.07H12v4.51h6.6c-.29 1.52-1.14 2.82-2.4 3.68v3.05h3.88c2.27-2.09 3.665-5.17 3.665-9.17z"/><path fill="#34A853" d="M12 24c3.24 0 5.95-1.08 7.93-2.91l-3.88-3.05c-1.08.72-2.45 1.16-4.05 1.16-3.12 0-5.77-2.1-6.72-4.93H1.25v3.15C3.26 21.36 7.33 24 12 24z"/><path fill="#FBBC05" d="M5.28 14.27c-.25-.72-.38-1.49-.38-2.27s.13-1.55.38-2.27V6.58H1.25C.45 8.18 0 9.99 0 12s.45 3.82 1.25 5.42l4.03-3.15z"/><path fill="#EA4335" d="M12 4.75c1.77 0 3.35.61 4.6 1.8l3.42-3.42C17.95 1.19 15.24 0 12 0 7.33 0 3.26 2.64 1.25 6.58l4.03 3.15c.95-2.83 3.6-4.98 6.72-4.98z"/></svg> 3344 <div style="text-align: left;"> 3345 <span class="google-brand-title">Google Reviews</span> 3346 <span style="display: block; font-size: 11px; color: #6b7280; font-weight: 600;">Kavya Global Network Nepal | #1 Brand for Study in USA & Australia</span> 3347 </div> 3348 </div> 3349 <div class="google-rating-divider"></div> 3350 <div class="google-stars-score"> 3351 <span class="google-score-number">${t.googleRating || '4.9'}</span> 3352 <div class="google-stars-icons"> 3353 <i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i> 3354 </div> 3355 <span class="google-review-count">(${t.googleReviewCount || '194'} Reviews)</span> 3356 </div> 3357 <div class="google-rating-divider"></div> 3358 <a href="${t.googleMapsUrl || 'https://www.google.com/search?q=Kavya+Global+Network'}" target="_blank" class="btn-view-google-reviews" title="View all reviews on Google"> 3359 <i class="fa-brands fa-google"></i> View on Google Maps <i class="fa-solid fa-arrow-up-right-from-square" style="font-size: 11px;"></i> 3360 </a> 3361 </div> 3362 </div> 3363 3364 <!-- 1 Single Line Slowly Scrolling Testimonials Track --> 3365 <div class="testimonials-scroll-container"> 3366 <div class="testimonials-scroll-track" style="animation-duration: ${duration}s;"> 3367 ${doubleList.map(r => ` 3368 <div class="google-review-card"> 3369 <div class="review-card-top"> 3370 <div class="review-user-info"> 3371 <img src="${r.avatar}" alt="${r.name}" class="review-user-avatar" loading="lazy" decoding="async" onerror="this.src='https://ui-avatars.com/api/?name=${encodeURIComponent(r.name)}&background=004a3e&color=fff';" /> 3372 <div class="review-meta-text"> 3373 <h5 class="review-user-name">${r.name}</h5> 3374 <span class="review-destination">${r.country || 'International Student'}</span> 3375 </div> 3376 </div> 3377 <svg class="review-google-badge" width="22" height="22" viewBox="0 0 24 24"><path fill="#4285F4" d="M23.745 12.27c0-.7-.06-1.4-.19-2.07H12v4.51h6.6c-.29 1.52-1.14 2.82-2.4 3.68v3.05h3.88c2.27-2.09 3.665-5.17 3.665-9.17z"/><path fill="#34A853" d="M12 24c3.24 0 5.95-1.08 7.93-2.91l-3.88-3.05c-1.08.72-2.45 1.16-4.05 1.16-3.12 0-5.77-2.1-6.72-4.93H1.25v3.15C3.26 21.36 7.33 24 12 24z"/><path fill="#FBBC05" d="M5.28 14.27c-.25-.72-.38-1.49-.38-2.27s.13-1.55.38-2.27V6.58H1.25C.45 8.18 0 9.99 0 12s.45 3.82 1.25 5.42l4.03-3.15z"/><path fill="#EA4335" d="M12 4.75c1.77 0 3.35.61 4.6 1.8l3.42-3.42C17.95 1.19 15.24 0 12 0 7.33 0 3.26 2.64 1.25 6.58l4.03 3.15c.95-2.83 3.6-4.98 6.72-4.98z"/></svg> 3378 </div> 3379 3380 <div class="review-stars-row"> 3381 <div class="review-stars-gold"> 3382 <i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i> 3383 </div>
3384 <span class="review-date-badge">${r.date || 'Verified Student'}</span> 3385 </div> 3386 3387 <p class="review-body-text">"${r.review}"</p> 3388 3389 <div class="review-card-footer"> 3390 <span class="google-verified-pill"> 3391 <i class="fa-solid fa-circle-check"></i> ${r.badge || 'Verified Google Review'} 3392 </span> 3393 <a href="${t.googleMapsUrl || 'https://www.google.com/search?q=Kavya+Global+Network'}" target="_blank" class="review-posted-on" title="View on Google"> 3394 Posted on Google <i class="fa-solid fa-arrow-up-right-from-square"></i> 3395 </a> 3396 </div> 3397 </div> 3398 `).join('')} 3399 </div> 3400 </div> 3401 </section> 3402 `; 3403 } 3404 3405 /* Frequently Asked Questions (SEO Rich Snippet Accordion) */ 3406 function renderFaqSection() { 3407 const faqs = siteData.faqs || { 3408 tag: "FREQUENTLY ASKED QUESTIONS", 3409 title: "Everything You Need to Know About Studying Abroad", 3410 description: "Clear, direct answers to common questions about admissions, test requirements, scholarships, and visa guidelines from Nepal.", 3411 items: [] 3412 }; 3413 3414 if (!faqs.items || faqs.items.length === 0) return ''; 3415 3416 return ` 3417 <section id="faqs" class="faq-section"> 3418 <div class="site-container"> 3419 <div class="section-header-center"> 3420 <span class="section-tag-pill"><i class="fa-solid fa-circle-question"></i> ${faqs.tag}</span> 3421 <h2 class="section-title-center" style="margin-top: 10px; font-size: 32px; font-weight: 800; color: #00332a;">${faqs.title}</h2> 3422 <p class="section-desc-center" style="max-width: 740px; margin: 0 auto 36px; color: #556965; font-size: 15px;">${faqs.description}</p> 3423 </div> 3424 3425 <div class="faq-accordion-wrap"> 3426 ${faqs.items.map((item, idx) => { 3427 const question = item.question || item.q || ''; 3428 const answer = item.answer || item.a || ''; 3429 return ` 3430 <div class="faq-item ${idx === 0 ? 'active' : ''}"> 3431 <button class="faq-question-btn" aria-expanded="${idx === 0 ? 'true' : 'false'}"> 3432 <span class="faq-q-text"><i class="fa-solid fa-graduation-cap" style="color: #006051; margin-right: 10px;"></i> ${question}</span> 3433 <i class="fa-solid fa-chevron-down faq-chevron"></i> 3434 </button> 3435 <div class="faq-answer-panel" style="${idx === 0 ? 'display: block;' : 'display: none;'}"> 3436 <p>${answer}</p> 3437 </div> 3438 </div> 3439 `; 3440 }).join('')} 3441 </div> 3442 3443 <div style="text-align: center; margin-top: 35px;"> 3444 <a href="/faqs" data-route="/faqs" class="link-all-destinations" style="display: inline-flex;"> 3445 Have More Questions? View All Frequently Asked Questions <i class="fa-solid fa-arrow-right"></i> 3446 </a> 3447 </div> 3448 </div> 3449 </section> 3450 `; 3451 } 3452 3453 /* Partner With Us Home Page Highlight Strip */ 3454 function renderHomePartnerCtaSection() { 3455 return ` 3456 <section class="home-partner-cta-strip"> 3457 <div class="site-container"> 3458 <div class="home-partner-cta-card"> 3459 <div class="home-partner-cta-left"> 3460 <span class="home-partner-tag"><i class="fa-solid fa-handshake"></i> FOR INSTITUTIONS & AGENTS</span> 3461 <h3 class="home-partner-title">Are you an International University, College or Regional Education Agent?</h3> 3462 <p class="home-partner-desc">Collaborate with Nepal's premier government-registered education network (MOEST Approval in Process). Access pre-screened genuine students, spot assessment events, and professional institutional partnerships.</p> 3463 <div class="home-partner-badges"> 3464 <span><i class="fa-solid fa-circle-check"></i> 60+ Direct Global Representations</span> 3465 <span><i class="fa-solid fa-circle-check"></i> 98% Visa Grant Success</span>
3466 <span><i class="fa-solid fa-circle-check"></i> Regional Associate Network</span> 3467 </div> 3468 </div> 3469 <div class="home-partner-cta-right"> 3470 <a href="/partner-with-us" data-route="/partner-with-us" class="btn-home-partner-primary"> 3471 <i class="fa-solid fa-briefcase"></i> Partner with Us <i class="fa-solid fa-arrow-right"></i> 3472 </a> 3473 <button type="button" onclick="window.openDispatchModal()" class="btn-home-partner-secondary" style="background: rgba(255,255,255,0.12); color: #ffffff; border: 1px solid rgba(252,155,9,0.5); cursor: pointer; display: inline-flex; align-items: center; gap: 8px;"> 3474 <i class="fa-solid fa-file-arrow-up" style="color: #fc9b09;"></i> B2B Document Dispatch 3475 </button> 3476 <a href="https://wa.me/9779709040360?text=Hello%2C%20I%20am%20interested%20in%20an%20institutional%2Fagent%20partnership%20with%20Kavya%20Global" target="_blank" rel="noopener" class="btn-home-partner-secondary"> 3477 <i class="fa-brands fa-whatsapp"></i> WhatsApp Desk 3478 </a> 3479 </div> 3480 </div> 3481 </div> 3482 </section> 3483 `; 3484 } 3485 3486 /* Dark Footer */ 3487 function renderFooter() { 3488 const { aboutText, quickLinks, countries } = siteData.footer; 3489 const { email, phone, mobilePhone, address } = siteData.general; 3490 return ` 3491 <footer id="contact" class="footer-dark-section"> 3492 <div class="site-container"> 3493 <div class="footer-main-grid"> 3494 <div class="footer-col"> 3495 <img src="/kavya-logo-official.png" alt="Kavya Global Logo" style="height: 54px; width: auto; margin-bottom: 20px; display: inline-block; background: #ffffff; padding: 8px 16px; border-radius: 10px; box-shadow: 0 6px 16px rgba(0,0,0,0.2);" /> 3496 <p>${aboutText}</p> 3497 <div class="social-links-row"> 3498 <a href="${siteData.footer && siteData.footer.social ? siteData.footer.social.facebook : 'https://www.facebook.com/officialkavyagroup'}" target="_blank" class="social-icon-btn" title="Facebook"><i class="fa-brands fa-facebook-f"></i></a> 3499 <a href="${siteData.footer && siteData.footer.social ? siteData.footer.social.instagram : 'https://www.instagram.com/officialkavyagroup/'}" target="_blank" class="social-icon-btn" title="Instagram"><i class="fa-brands fa-instagram"></i></a> 3500 <a href="${siteData.footer && siteData.footer.social ? siteData.footer.social.youtube : 'https://www.youtube.com/channel/UCcbNsbtVl8BLHKFFe7JWFdQ/posts?pvf=CAI%253D'}" target="_blank" class="social-icon-btn" title="YouTube"><i class="fa-brands fa-youtube"></i></a> 3501 <a href="${siteData.footer && siteData.footer.social ? siteData.footer.social.linkedin : 'https://www.linkedin.com/in/kavya-global-network-8b1807359/'}" target="_blank" class="social-icon-btn" title="LinkedIn"><i class="fa-brands fa-linkedin-in"></i></a> 3502 </div> 3503 </div> 3504 3505 <div class="footer-col"> 3506 <h4>Quick Links</h4> 3507 <ul class="footer-list"> 3508 ${quickLinks.map(l => `<li><a href="${l.url}" ${l.url.startsWith('/') ? `data-route="${l.url}"` : ''}>${l.name}</a></li>`).join('')} 3509 </ul> 3510 </div> 3511 3512 <div class="footer-col"> 3513 <h4>Countries</h4> 3514 <ul class="footer-list"> 3515 ${countries.map(c => `<li><a href="${c.url}" ${c.url.startsWith('/') ? `data-route="${c.url}"` : ''}>${c.name}</a></li>`).join('')} 3516 </ul> 3517 </div> 3518 3519 <div class="footer-col"> 3520 <h4>Contact Us</h4> 3521 <ul class="contact-items-list"> 3522 <li> 3523 <i class="fa-solid fa-location-dot"></i> 3524 <span>${address} <br><small style="color: #03989e; font-size: 11.5px; display: block; margin-top: 3px;">(Centrally located between New Baneshwor & Tinkune)</small></span> 3525 </li> 3526 <li><i class="fa-solid fa-phone"></i> Landline: <a href="tel:${phone}" style="color: #fff; text-decoration: none;">${phone}</a></li> 3527 <li class="contact-whatsapp-item"><i class="fa-brands fa-whatsapp"></i> <span>WhatsApp: <a href="https://wa.me/9779709040360" target="_blank" style="color: #25d366; font-weight: 700; text-decoration: none;">+977 9709040360</a> / <a href="https://wa.me/9779709040350" target="_blank" style="color: #25d366; font-weight: 700; text-decoration: none;">9709040350</a></span></li> 3528 <li><i class="fa-solid fa-envelope"></i> <a href="mailto:${email}" style="color: #fff; text-decoration: none;">${email}</a></li> 3529 </ul> 3530 </div> 3531 3532 <div class="footer-col"> 3533 <h4>Stay Informed</h4> 3534 <p style="font-size: 12px;">Subscribe to get the latest updates on abroad education.</p> 3535 <div class="newsletter-box"> 3536 <input type="email" placeholder="Enter your email" /> 3537 <button class="btn-subscribe">SUBSCRIBE</button> 3538 </div> 3539 </div> 3540 </div> 3541 3542 <div class="footer-bottom-bar"> 3543 <div>© ${new Date().getFullYear()} Kavya Global Network. All Rights Reserved.</div> 3544 <div class="footer-legal-links"> 3545 <a href="/privacy-policy" data-route="/privacy-policy">Privacy Policy</a> 3546 <a href="/terms" data-route="/terms">Terms of Service</a> 3547 <a href="/faqs" data-route="/faqs">Frequently Asked Questions</a> 3548 </div> 3549 </div> 3550 </div> 3551 </footer> 3552 `; 3553 } 3554 3555 /* Floating Modern Quick-Contact Widget */ 3556 function renderFloatingContacts() { 3557 return ` 3558 <div class="floating-quick-dock" id="floating-quick-dock" aria-label="Quick Connect Support"> 3559 <a href="https://wa.me/9779709040360?text=Hello%20Kavya%20Global%2C%20I%20would%20like%20to%20inquire
3559%20about%20abroad%20studies." 3560 class="floating-dock-pill whatsapp" 3561 target="_blank" 3562 rel="noopener noreferrer" 3563 title="Direct WhatsApp Helpline"> 3564 <div class="dock-icon-circle whatsapp-pulse"> 3565 <i class="fa-brands fa-whatsapp"></i> 3566 </div> 3567 <div class="dock-content"> 3568 <span class="dock-badge"><span class="live-dot green"></span> Online</span> 3569 <span class="dock-text">WhatsApp Helpline</span> 3570 </div> 3571 </a> 3572 3573 <a href="tel:+97714106821" 3574 class="floating-dock-pill phone" 3575 title="Direct Telephone Helpline"> 3576 <div class="dock-icon-circle phone-pulse"> 3577 <i class="fa-solid fa-phone-volume"></i> 3578 </div> 3579 <div class="dock-content"> 3580 <span class="dock-badge"><span class="live-dot orange"></span> Office Desk</span> 3581 <span class="dock-text">+977 1-4106821</span> 3582 </div> 3583 </a> 3584 </div> 3585 `; 3586 } 3587 3588 /* Premium App-like Mobile Bottom Navigation Bar (Thumb Friendly) */ 3589 function renderMobileBottomBar() { 3590 const currentPath = window.location.pathname.replace(/\/$/, '') || '/'; 3591 return ` 3592 <nav class="mobile-bottom-nav" aria-label="Mobile Bottom Quick Navigation"> 3593 <a href="/" data-route="/" class="mob-bottom-tab ${currentPath === '/' && !isMobileMenuOpen ? 'active' : ''}"> 3594 <i class="fa-solid fa-house"></i> 3595 <span>Home</span> 3596 </a> 3597 <a href="/destinations" data-route="/destinations" class="mob-bottom-tab ${currentPath.startsWith('/destinations') && !isMobileMenuOpen ? 'active' : ''}"> 3598 <i class="fa-solid fa-earth-americas"></i> 3599 <span>Destinations</span> 3600 </a> 3601 <button class="mob-bottom-tab mob-bottom-counsel-btn btn-trigger-mock-test" aria-label="Register for Free Mock Test" title="Register for Free Mock Test"> 3602 <div class="mob-counsel-circle" style="background: linear-gradient(135deg, #fc9b09 0%, #e08600 100%); box-shadow: 0 4px 15px rgba(252, 155, 9, 0.45);"> 3603 <i class="fa-solid fa-laptop-code"></i> 3604 </div> 3605 <span>Mock Test</span> 3606 </button> 3607 <a href="/services" data-route="/services" class="mob-bottom-tab ${currentPath.startsWith('/services') && !isMobileMenuOpen ? 'active' : ''}"> 3608 <i class="fa-solid fa-briefcase"></i> 3609 <span>Services</span> 3610 </a> 3611 <button id="mob-bottom-menu-toggle" class="mob-bottom-tab btn-toggle-mobile-menu ${isMobileMenuOpen ? 'active' : ''}" aria-label="Toggle navigation menu" title="Open Navigation Menu"> 3612 <i class="fa-solid ${isMobileMenuOpen ? 'fa-xmark' : 'fa-bars'}"></i> 3613 <span>${isMobileMenuOpen ? 'Close' : 'Menu'}</span> 3614 </button> 3615 </nav> 3616 `; 3617 } 3618 3619 /* Mobile Off-Canvas Navigation Drawer */ 3620 function renderMobileDrawer() { 3621 if (!isMobileMenuOpen) return ''; 3622 const currentPath = window.location.pathname.replace(/\/$/, '') || '/'; 3623 return ` 3624 <div class="mobile-drawer-overlay" id="mobile-drawer-backdrop"> 3625 <div class="mobile-drawer-card"> 3626 <div class="mobile-drawer-header"> 3627 <div class="mobile-drawer-brand"> 3628 <img src="/kavya-logo-official.png" alt="Kavya Global Logo" class="mobile-drawer-logo" /> 3629 <div class="mobile-drawer-meta"> 3630 <span class="mobile-drawer-license"><i class="fa-solid fa-shield-halved"></i> MOEST (Approval in Process)</span> 3631 </div> 3632 </div> 3633 <button id="btn-close-mobile-drawer" class="btn-close-mobile-drawer" aria-label="Close navigation menu"> 3634 <i class="fa-solid fa-xmark"></i> 3635 </button> 3636 </div> 3637 3638 <div class="mobile-drawer-body"> 3639 <nav class="mobile-nav-list"> 3640 <a href="/" class="mobile-nav-item ${currentPath === '/' ? 'active' : ''}" data-route="/"> 3641 <i class="fa-solid fa-house"></i> Home 3642 </a> 3643 3644 <div class="mobile-nav-group-title">Who Are We?</div> 3645 <a href="/about" class="mobile-nav-item ${currentPath === '/about' ? 'active' : ''}" data-route="/about"> 3646 <i class="fa-solid fa-building-columns"></i> About Kavya Network 3647 </a> 3648 <a href="/leadership-message" class="mobile-nav-item ${currentPath === '/leadership-message' ? 'active' : ''}" data-route="/leadership-message"> 3649 <i class="fa-solid fa-user-tie"></i> Leadership Message 3650 </a> 3651 <a href="/accreditations" class="mobile-nav-item ${currentPath === '/accreditations' ? 'active' : ''}" data-route="/accreditations"> 3652 <i class="fa-solid fa-award"></i> Accreditations & Licenses 3653 </a> 3654 <a href="/visa-success" class="mobile-nav-item ${currentPath === '/visa-success' ? 'active' : ''}" data-route="/visa-success"> 3655 <i class="fa-solid fa-passport"></i>
3655 Visa Success Stories (98%) 3656 </a> 3657 <a href="/b2b" class="mobile-nav-item ${currentPath === '/b2b' ? 'active' : ''}" data-route="/b2b"> 3658 <i class="fa-solid fa-handshake"></i> Partner with Us <span class="mobile-b2b-pill">B2B Portal</span> 3659 </a> 3660 <a href="/b2b#b2b-institutions" class="mobile-nav-item" data-route="/b2b#b2b-institutions"> 3661 <i class="fa-solid fa-building-columns"></i> Represented Institutions 3662 </a> 3663 <a href="/b2b#b2b-tracks" class="mobile-nav-item" data-route="/b2b#b2b-tracks"> 3664 <i class="fa-solid fa-road-branch"></i> Collaboration Tracks 3665 </a> 3666 <a href="/b2b#b2b-why-partner" class="mobile-nav-item" data-route="/b2b#b2b-why-partner"> 3667 <i class="fa-solid fa-trophy"></i> Why Choose Kavya 3668 </a> 3669 <a href="/b2b#partner-form-anchor" class="mobile-nav-item" data-route="/b2b#partner-form-anchor"> 3670 <i class="fa-solid fa-briefcase"></i> Corporate Desk & Meeting 3671 </a> 3672 3673 <div class="mobile-nav-group-title">Study Destinations</div> 3674 <div class="mobile-dest-grid"> 3675 <a href="/destinations/australia" class="mobile-dest-chip" data-route="/destinations/australia"><img src="/flags/au.svg" alt="Australia" class="mobile-dest-flag-img" loading="lazy" decoding="async" /> Australia</a> 3676 <a href="/destinations/canada" class="mobile-dest-chip" data-route="/destinations/canada"><img src="/flags/ca.svg" alt="Canada" class="mobile-dest-flag-img" loading="lazy" decoding="async" /> Canada</a> 3677 <a href="/destinations/uk" class="mobile-dest-chip" data-route="/destinations/uk"><img src="/flags/gb.svg" alt="UK" class="mobile-dest-flag-img" loading="lazy" decoding="async" /> UK</a> 3678 <a href="/destinations/usa" class="mobile-dest-chip" data-route="/destinations/usa"><img src="/flags/us.svg" alt="USA" class="mobile-dest-flag-img" loading="lazy" decoding="async" /> USA</a> 3679 <a href="/destinations/japan" class="mobile-dest-chip" data-route="/destinations/japan"><img src="/flags/jp.svg" alt="Japan" class="mobile-dest-flag-img" loading="lazy" decoding="async" /> Japan</a> 3680 <a href="/destinations/korea" class="mobile-dest-chip" data-route="/destinations/korea"><img src="/flags/kr.svg" alt="Korea" class="mobile-dest-flag-img" loading="lazy" decoding="async" /> Korea</a> 3681 <a href="/destinations/germany" class="mobile-dest-chip" data-route="/destinations/germany"><img src="/flags/de.svg" alt="Germany" class="mobile-dest-flag-img" loading="lazy" decoding="async" /> Germany</a> 3682 <a href="/destinations" class="mobile-dest-chip all-chip" data-route="/destinations">ð All Countries</a> 3683 </div> 3684 3685 <div class="mobile-nav-group-title">Our Services</div> 3686 <a href="/services" class="mobile-nav-item ${currentPath === '/services' ? 'active' : ''}" data-route="/services"> 3687 <i class="fa-solid fa-layer-group"></i> All Services Overview 3688 </a> 3689 <a href="/services/career-counseling" class="mobile-nav-item" data-route="/services/career-counseling"> 3690 <i class="fa-solid fa-comments"></i> Career Counseling 3691 </a> 3692 <a href="/services/university-admissions" class="mobile-nav-item" data-route="/services/university-admissions"> 3693 <i class="fa-solid fa-graduation-cap"></i> University Admissions & Scholarships 3694 </a> 3695 <a href="/services/visa-documentation" class="mobile-nav-item" data-route="/services/visa-documentation"> 3696 <i class="fa-solid fa-file-shield"></i> Visa Documentation & SOP 3697 </a> 3698 <a href="/services/interview-prep" class="mobile-nav-item" data-route="/services/interview-prep"> 3699 <i class="fa-solid fa-user-check"></i> Visa Mock Interview Prep 3700 </a> 3701 <a href="/services/pre-departure" class="mobile-nav-item" data-route="/services/pre-departure"> 3702 <i class="fa-solid fa-plane-departure"></i> Pre-Departure Briefing 3703 </a> 3704 3705 <div class="mobile-nav-group-title">Test Preparation</div> 3706 <a href="/test-prep/pte" class="mobile-nav-item" data-route="/test-prep/pte"> 3707 <i class="fa-solid fa-laptop-code"></i>
3707 PTE Academic (AI Lab) 3708 </a> 3709 <a href="/test-prep/ielts" class="mobile-nav-item" data-route="/test-prep/ielts"> 3710 <i class="fa-solid fa-pen-nib"></i> IELTS Preparation 3711 </a> 3712 <a href="/mock-test" class="mobile-nav-item" data-route="/mock-test" style="color: #fc9b09; font-weight: 800;"> 3713 <i class="fa-solid fa-calendar-check"></i> Register Free Mock Test 3714 </a> 3715 3716 <div class="mobile-nav-group-title">Help & Contact</div> 3717 <a href="/contact" class="mobile-nav-item ${currentPath === '/contact' ? 'active' : ''}" data-route="/contact"> 3718 <i class="fa-solid fa-envelope"></i> Contact Us (New Baneshwor) 3719 </a> 3720 <a href="/faqs" class="mobile-nav-item ${currentPath === '/faqs' ? 'active' : ''}" data-route="/faqs"> 3721 <i class="fa-solid fa-circle-question"></i> Frequently Asked Questions 3722 </a> 3723 </nav> 3724 </div> 3725 3726 <div class="mobile-drawer-footer"> 3727 <div class="mobile-drawer-quick-actions"> 3728 <a href="https://wa.me/9779709040360" target="_blank" rel="noopener noreferrer" class="mobile-action-wa"> 3729 <i class="fa-brands fa-whatsapp"></i> WhatsApp Chat 3730 </a> 3731 <a href="tel:+97714106821" class="mobile-action-call"> 3732 <i class="fa-solid fa-phone"></i> +977 1-4106821 3733 </a> 3734 </div> 3735 </div> 3736 </div> 3737 </div> 3738 `; 3739 } 3740 3741 /* Online Counseling Pop-up Modal */ 3742 function renderCounselingModal() { 3743 const sessionType = counselingState.sessionType || 'whatsapp-video'; 3744 return ` 3745 <div class="counseling-modal-overlay" id="counseling-backdrop"> 3746 <div class="counseling-modal-card counseling-modal-wide"> 3747 3748 <!-- Header --> 3749 <div class="counseling-modal-header"> 3750 <div class="counseling-header-left"> 3751 <span class="counseling-live-badge"><span class="counseling-live-dot"></span> LIVE ⢠AVAILABLE NOW</span> 3752 <h3><i class="fa-solid fa-headset"></i> Book Free Study Abroad Counseling</h3> 3753 <p>1-on-1 personalized profile evaluation with senior certified counselors (Govt. Regd. Consultancy).</p> 3754 </div> 3755 <button id="btn-close-counseling-modal" class="btn-close-counseling" aria-label="Close Modal"><i class="fa-solid fa-xmark"></i></button> 3756 </div> 3757 3758 <!-- Video Counseling Quick Feature Highlights Strip --> 3759 <div class="counseling-highlights-strip"> 3760 <div class="c-hl-item"><i class="fa-solid fa-circle-check"></i> 100% Free Session</div> 3761 <div class="c-hl-item"><i class="fa-solid fa-circle-check"></i> Senior Counselors</div> 3762 <div class="c-hl-item"><i class="fa-solid fa-circle-check"></i> No App Download</div> 3763 <div class="c-hl-item"><i class="fa-solid fa-circle-check"></i> Flexible Timing</div> 3764 </div> 3765 3766 <!-- Session Type Picker --> 3767 <div class="counseling-type-row"> 3768 <button class="counseling-type-btn ${sessionType === 'whatsapp-video' ? 'active' : ''}" data-session="whatsapp-video"> 3769 <span class="counseling-type-icon" style="background: linear-gradient(135deg,#25d366,#128c7e);"> 3770 <i class="fa-brands fa-whatsapp"></i> 3771 </span> 3772 <span class="counseling-type-info"> 3773 <strong>
3773WhatsApp Video Call</strong> 3774 <small>Connect from anywhere in Nepal â 100% Free</small> 3775 </span> 3776 <span class="counseling-type-badge">â Recommended</span> 3777 </button> 3778 3779 <button class="counseling-type-btn ${sessionType === 'in-person' ? 'active' : ''}" data-session="in-person"> 3780 <span class="counseling-type-icon" style="background: linear-gradient(135deg,#004a3e,#006051);"> 3781 <i class="fa-solid fa-building-columns"></i> 3782 </span> 3783 <span class="counseling-type-info"> 3784 <strong>In-Person (Kathmandu)</strong> 3785 <small>New Baneshwor Head Office</small> 3786 </span> 3787 </button> 3788 3789 <button class="counseling-type-btn ${sessionType === 'phone-call' ? 'active' : ''}" data-session="phone-call"> 3790 <span class="counseling-type-icon" style="background: linear-gradient(135deg,#fc9b09,#e08600);"> 3791 <i class="fa-solid fa-phone"></i> 3792 </span> 3793 <span class="counseling-type-info"> 3794 <strong>Phone Call</strong> 3795 <small>Direct telephone discussion</small> 3796 </span> 3797 </button> 3798 </div> 3799 3800 <!-- WhatsApp video callout --> 3801 ${sessionType === 'whatsapp-video' ? ` 3802 <div class="whatsapp-video-callout"> 3803 <div class="wvc-icon-wrap"><i class="fa-brands fa-whatsapp"></i></div> 3804 <div class="wvc-text"> 3805 <strong>How it works:</strong> After booking, our counselor will send you a WhatsApp Video Call invite at your preferred time. No app downloads required â just WhatsApp! 3806 </div> 3807 <a href="https://wa.me/9779709040360?text=Hi%2C%20I%20want%20to%20book%20a%20WhatsApp%20Video%20Counseling%20session" target="_blank" rel="noopener" class="wvc-direct-btn"> 3808 <i class="fa-brands fa-whatsapp"></i> Chat Now Instead 3809 </a> 3810 </div> 3811 ` : ''} 3812 3813 <div class="counseling-modal-body"> 3814 ${counselingStatus ? ` 3815 <div style="padding: 12px 16px; border-radius: 10px; font-size: 13.5px; font-weight: 600; margin-bottom: 16px; ${counselingStatus.type === 'success' ? 'background: #d4edda; color: #155724; border-left: 4px solid #28a745;' : 'background: #f8d7da; color: #721c24; border-left: 4px solid #dc3545;'}"> 3816 ${counselingStatus.text} 3817 </div> 3818 ` : ''} 3819 3820 <form id="counseling-modal-form"> 3821 <div class="counseling-form-grid"> 3822 <div class="counseling-field-group"> 3823 <label>Full Name *</label> 3824 <input type="text" id="counsel-name" placeholder="Enter your full name" value="${counselingState.name}" required /> 3825 </div> 3826 <div class="counseling-field-group"> 3827 <label>Email Address *</label> 3828 <input type="email" id="counsel-email" placeholder="Enter your email" value="${counselingState.email}" required /> 3829 </div> 3830 </div> 3831 3832 <div class="counseling-form-grid"> 3833 <div class="counseling-field-group"> 3834 <label>${sessionType === 'whatsapp-video' ? 'WhatsApp Number *' : 'Phone / WhatsApp *'}</label> 3835 <input type="tel" id="counsel-phone" placeholder="Enter your phone / WhatsApp number" value="${counselingState.phone}" required /> 3836 ${sessionType === 'whatsapp-video' ? '<small style="color:#25d366;font-size:11.5px;font-weight:600;margin-top:4px;display:block;"><i class="fa-brands fa-whatsapp"></i> We\'ll call you on this WhatsApp number</small>' : ''} 3837 </div> 3838 <div class="counseling-field-group"> 3839 <label>Target Country *</label> 3840 <select id="counsel-country"> 3841 <option value="USA" ${counselingState.country === 'USA' ? 'selected' : ''}>ðºð¸ Study in USA</option> 3842 <option value="Australia" ${counselingState.country === 'Australia' ? 'selected' : ''}>ð¦ðº Study in Australia</option> 3843 <option value="UK" ${counselingState.country === 'UK' ? 'selected' : ''}>ð¬ð§ Study in UK</option> 3844 <option value="Canada" ${counselingState.country === 'Canada' ? 'selected' : ''}>ð¨ð¦ Study in Canada</option> 3845 <option value="Germany" ${counselingState.country === 'Germany' ? 'selected' : ''}>ð©ðª Study in Germany</option> 3846 <option value="Europe" ${counselingState.country === 'Europe' ? 'selected' : ''}>ðªðº Study in Europe / Other</option> 3847 </select> 3848 </div> 3849 </div> 3850 3851 <div class="counseling-field-group"> 3852 <label>Preferred Date & Time</label> 3853 <input type="text" id="counsel-date" placeholder="Preferred date and time (or flexible)" value="${counselingState.preferredDate}" /> 3854 </div> 3855 3856 <div class="counseling-field-group"> 3857 <label>Academic Query / Notes (Optional)</label> 3858 <textarea id="counsel-msg" placeholder="Tell us about your qual
3858ification, target course, or any specific query..." style="height: 70px; resize: vertical;">${counselingState.message}</textarea> 3859 </div> 3860 3861 <button type="submit" class="btn-submit-counseling ${sessionType === 'whatsapp-video' ? 'btn-submit-whatsapp' : ''}"> 3862 ${sessionType === 'whatsapp-video' 3863 ? '<i class="fa-brands fa-whatsapp"></i> CONFIRM WHATSAPP VIDEO CALL BOOKING' 3864 : sessionType === 'in-person' 3865 ? '<i class="fa-solid fa-building-columns"></i> BOOK IN-PERSON APPOINTMENT' 3866 : '<i class="fa-solid fa-phone"></i> CONFIRM PHONE CALL BOOKING' 3867 } 3868 </button> 3869 </form> 3870 </div> 3871 </div> 3872 </div> 3873 `; 3874 } 3875 3876 /* Modal â Free Mock Test Registration */ 3877 function renderMockTestModal() { 3878 return ` 3879 <div class="counseling-modal-overlay" id="mock-modal-backdrop"> 3880 <div class="counseling-modal-card" style="max-width: 580px;"> 3881 <div class="counseling-modal-header" style="background: linear-gradient(135deg, #00332a 0%, #004a3e 100%);"> 3882 <div class="counseling-header-left"> 3883 <span class="counseling-live-badge"><span class="counseling-live-dot" style="background: #fc9b09;"></span> 100% FREE ⢠COMPUTERIZED TESTING LAB</span> 3884 <h3><i class="fa-solid fa-laptop-code" style="color: #fc9b09;"></i> Register for Free Mock Test</h3> 3885 <p>Authentic Pearson & British Council format with instant AI diagnostic score.</p> 3886 </div> 3887 <button id="btn-close-mock-modal" class="btn-close-counseling" aria-label="Close Modal"><i class="fa-solid fa-xmark"></i></button> 3888 </div> 3889 3890 <div class="counseling-modal-body"> 3891 ${formStatus ? ` 3892 <div style="padding: 12px 16px; border-radius: 10px; font-size: 13.5px; font-weight: 600; margin-bottom: 16px; ${formStatus.type === 'success' ? 'background: #d4edda; color: #155724; border-left: 4px solid #28a745;' : 'background: #f8d7da; color: #721c24; border-left: 4px solid #dc3545;'}"> 3893 ${formStatus.text} 3894 </div> 3895 ` : ''} 3896 3897 <form id="mock-modal-form"> 3898 <div class="counseling-form-grid"> 3899 <div class="counseling-field-group"> 3900 <label>Full Name *</label> 3901 <input type="text" name="name" id="mock-m-name" placeholder="Enter your full name" value="${formState.name || ''}" required /> 3902 </div> 3903 <div class="counseling-field-group"> 3904 <label>Phone / WhatsApp Number *</label> 3905 <input type="tel" name="phone" id="mock-m-phone" placeholder="e.g. 98XXXXXXXX" value="${formState.phone || ''}" required /> 3906 </div> 3907 </div> 3908 3909 <div class="counseling-form-grid"> 3910 <div class="counseling-field-group"> 3911 <label>Email Address *</label> 3912 <input type="email" name="email" id="mock-m-email" placeholder="Enter your email" value="${formState.email || ''}" required /> 3913 </div> 3914 <div class="counseling-field-group"> 3915 <label>Target Destination</label> 3916 <select name="address" id="mock-m-address"> 3917 <option value="Australia">Study in Australia</option> 3918 <option value="USA">Study in USA</option> 3919 <option value="UK">Study in UK</option> 3920 <option value="Canada">Study in Canada</option> 3921 <option value="Europe">Study in Europe</option> 3922 <option value="Other">Other</option> 3923 </select> 3924 </div> 3925 </div> 3926 3927 <div class="counseling-form-grid"> 3928 <div class="counseling-field-group"> 3929 <label>Test Type *</label> 3930 <select name="testType" id="mock-m-testtype" required> 3931 <option value="PTE Academic" ${formState.testType === 'PTE Academic' ? 'selected' : ''}>
3931PTE Academic (AI Lab Mock)</option> 3932 <option value="IELTS Academic" ${formState.testType === 'IELTS Academic' ? 'selected' : ''}>IELTS Academic</option> 3933 <option value="IELTS General" ${formState.testType === 'IELTS General' ? 'selected' : ''}>IELTS General Training</option> 3934 <option value="TOEFL" ${formState.testType === 'TOEFL' ? 'selected' : ''}>TOEFL</option> 3935 </select> 3936 </div> 3937 <div class="counseling-field-group"> 3938 <label>Preferred Time Slot *</label> 3939 <select name="timeSlot" id="mock-m-timeslot" required> 3940 <option value="08:00 AM - 11:00 AM">Morning: 08:00 AM â 11:00 AM</option> 3941 <option value="11:30 AM - 02:30 PM">Mid-Day: 11:30 AM â 02:30 PM</option> 3942 <option value="03:00 PM - 06:00 PM">Afternoon: 03:00 PM â 06:00 PM</option> 3943 </select> 3944 </div> 3945 </div> 3946 3947 <div class="counseling-field-group"> 3948 <label>Preferred Test Date</label> 3949 <input type="date" name="date" id="mock-m-date" value="${formState.date || ''}" /> 3950 </div> 3951 3952 <button type="submit" class="btn-submit-counseling" style="background: linear-gradient(135deg, #fc9b09 0%, #e08600 100%); color: #ffffff; font-weight: 800; letter-spacing: 0.5px;"> 3953 <i class="fa-solid fa-circle-check"></i> CONFIRM FREE MOCK TEST SLOT 3954 </button> 3955 </form> 3956 </div> 3957 </div> 3958 </div> 3959 `; 3960 } 3961 3962 3963 /* Dedicated Full-Screen Professional Admin Portal Dashboard */ 3964 function renderAdminPortal() { 3965 return `
3966 <div class="admin-portal-wrapper"> 3967 <header class="admin-portal-navbar"> 3968 <div class="admin-nav-brand"> 3969 <img src="/kavya-logo-official.png" alt="Kavya Global" /> 3970 <span class="admin-nav-brand-title">KAVYA GLOBAL NETWORK</span> 3971 <span class="admin-nav-brand-badge">ADMIN CMS</span> 3972 </div> 3973 <div class="admin-nav-right"> 3974 <button id="btn-view-live-site" class="btn-view-live-site"> 3975 <i class="fa-solid fa-arrow-left"></i> View Live Website 3976 </button> 3977 <button id="btn-admin-logout" class="btn-logout-portal"> 3978 <i class="fa-solid fa-right-from-bracket"></i> Logout 3979 </button> 3980 </div> 3981 </header> 3982 3983 <div class="admin-portal-body"> 3984 <aside class="admin-portal-sidebar"> 3985 <div class="admin-sidebar-section"> 3986 <div class="admin-sidebar-label">Header & Navigation</div> 3987 <button class="admin-sidebar-item ${activeAdminTab === 'topbar' ? 'active' : ''}" data-tab="topbar"> 3988 <span><i class="fa-solid fa-phone-volume"></i> Top Bar & Contacts</span> 3989 </button> 3990 <button class="admin-sidebar-item ${activeAdminTab === 'header' ? 'active' : ''}" data-tab="header"> 3991 <span><i class="fa-solid fa-heading"></i> Header & Nav</span> 3992 </button> 3993 <button class="admin-sidebar-item ${activeAdminTab === 'hero' ? 'active' : ''}" data-tab="hero"> 3994 <span><i class="fa-solid fa-house"></i> Hero Section</span> 3995 </button> 3996 <button class="admin-sidebar-item ${activeAdminTab === 'counters' ? 'active' : ''}" data-tab="counters"> 3997 <span><i class="fa-solid fa-chart-simple"></i> Stats Counters</span> 3998 </button> 3999 </div> 4000 4001 <div class="admin-sidebar-section"> 4002 <div class="admin-sidebar-label">Main Content Sections</div> 4003 <button class="admin-sidebar-item ${activeAdminTab === 'about' ? 'active' : ''}" data-tab="about"> 4004 <span><i class="fa-solid fa-building-columns"></i> About Page</span> 4005 </button> 4006 <button class="admin-sidebar-item ${activeAdminTab === 'director' ? 'active' : ''}" data-tab="director"> 4007 <span><i class="fa-solid fa-user-tie"></i> Leadership Message</span> 4008 </button> 4009 <button class="admin-sidebar-item ${activeAdminTab === 'partners' ? 'active' : ''}" data-tab="partners"> 4010 <span><i class="fa-solid fa-handshake"></i> Partner Logos</span> 4011 </button> 4012 <button class="admin-sidebar-item ${activeAdminTab === 'services' ? 'active' : ''}" data-tab="services"> 4013 <span><i class="fa-solid fa-briefcase"></i> Services</span> 4014 </button> 4015 <button class="admin-sidebar-item ${activeAdminTab === 'destinations' ? 'active' : ''}" data-tab="destinations"> 4016 <span><i class="fa-solid fa-globe"></i> Destinations</span> 4017 </button> 4018 <button class="admin-sidebar-item ${activeAdminTab === 'visaSuccess' ? 'active' : ''}" data-tab="visaSuccess"> 4019 <span><i class="fa-solid fa-passport"></i> Visa Approvals</span> 4020 </button> 4021 <button class="admin-sidebar-item ${activeAdminTab === 'testPrep' ? 'active' : ''}" data-tab="testPrep"> 4022 <span><i class="fa-solid fa-pen-to-square"></i> Test Prep & Form</span> 4023 </button> 4024 <button class="admin-sidebar-item ${activeAdminTab === 'accreditations' ? 'active' : ''}" data-tab="accreditations"> 4025 <span><i class="fa-solid fa-award"></i> Accreditations</span> 4026 </button> 4027 <button class="admin-sidebar-item ${activeAdminTab === 'testimonials' ? 'active' : ''}" data-tab="testimonials"> 4028 <span><i class="fa-solid fa-comments"></i> Student Reviews</span> 4029 </button> 4030 <button class="admin-sidebar-item ${activeAdminTab === 'faqs' ? 'active' : ''}" data-tab="faqs">
4031 <span><i class="fa-solid fa-circle-question"></i> FAQs Accordion</span> 4032 </button> 4033 <button class="admin-sidebar-item ${activeAdminTab === 'footer' ? 'active' : ''}" data-tab="footer"> 4034 <span><i class="fa-solid fa-shoe-prints"></i> Footer & Links</span> 4035 </button> 4036 </div> 4037 4038 <div class="admin-sidebar-section"> 4039 <div class="admin-sidebar-label">Leads & Registrations</div> 4040 <button class="admin-sidebar-item ${activeAdminTab === 'leads' ? 'active' : ''}" data-tab="leads"> 4041 <span><i class="fa-solid fa-users"></i> Lead Submissions</span> 4042 <span class="admin-badge-count" style="background: rgba(255,255,255,0.18); padding: 2px 8px; border-radius: 10px; font-size: 11px;">${formSubmissions.length}</span> 4043 </button> 4044 <button class="admin-sidebar-item ${activeAdminTab === 'partnerApps' ? 'active' : ''}" data-tab="partnerApps"> 4045 <span><i class="fa-solid fa-handshake-angle"></i> Partner Applications</span> 4046 <span class="admin-badge-count" style="background: rgba(252,155,9,0.35); color: #fff; padding: 2px 8px; border-radius: 10px; font-size: 11px; font-weight: 700;">${partnerApps.length}</span> 4047 </button> 4048 </div> 4049 4050 <div class="admin-sidebar-section"> 4051 <div class="admin-sidebar-label">Settings & Security</div> 4052 <button class="admin-sidebar-item ${activeAdminTab === 'general' ? 'active' : ''}" data-tab="general"> 4053 <span><i class="fa-solid fa-sliders"></i> General & Security</span> 4054 </button> 4055 </div> 4056 </aside> 4057
4058 <main class="admin-portal-content"> 4059 ${renderAdminTabContent()} 4060 </main> 4061 </div> 4062 </div> 4063 `; 4064 } 4065 4066 function renderAdminTabContent() { 4067 switch (activeAdminTab) { 4068 case 'topbar': 4069 const top = siteData.topBar || {}; 4070 return ` 4071 <div class="admin-section-editor"> 4072 <h3><i class="fa-solid fa-phone-volume"></i> Top Bar & Contact Information</h3> 4073 <p style="color: #666; font-size: 13px; margin-bottom: 20px;">Manage the top contact strip, landline, WhatsApp hotlines, email, and announcement banner.</p> 4074 <div class="admin-form-group"> 4075 <label>Landline Phone</label> 4076 <input type="text" id="admin-topbar-phone" value="${top.phone || '+977 1-4106821'}" /> 4077 </div> 4078 <div class="admin-form-group"> 4079 <label>WhatsApp / Mobile Hotline</label> 4080 <input type="text" id="admin-topbar-mobile" value="${top.mobile || '+977 9709040360 / +977 9709040350'}" /> 4081 </div> 4082 <div class="admin-form-group"> 4083 <label>Official Email Address</label> 4084 <input type="email" id="admin-topbar-email" value="${top.email || '[email protected]'}" /> 4085 </div> 4086 <div class="admin-form-group"> 4087 <label>Office Address</label> 4088 <input type="text" id="admin-topbar-address" value="${top.address || 'Aloknagar Gate, New Baneshwor, Kathmandu, Nepal'}" /> 4089 </div> 4090 <div class="admin-form-group"> 4091 <label>Top Announcement Banner (Optional)</label> 4092 <input type="text" id="admin-topbar-announcement" value="${top.announcement || ''}" placeholder="ð Admissions Open: USA, Australia & Germany Fall 2026..." /> 4093 </div> 4094 <button id="btn-save-topbar" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save Top Bar Settings</button> 4095 </div> 4096 `; 4097 4098 case 'header': 4099 return ` 4100 <div class="admin-section-editor"> 4101 <h3><i class="fa-solid fa-heading"></i> Header & Navigation Branding</h3> 4102 <div class="admin-form-group"> 4103 <label>Header Logo Image URL</label> 4104 <input type="text" id="admin-header-logo" value="${siteData.header ? siteData.header.logoUrl || '/kavya-logo-official.png' : '/kavya-logo-official.png'}" /> 4105 </div> 4106 <div class="admin-form-group"> 4107 <label>Counseling Action Button Text</label> 4108 <input type="text" id="admin-header-btn" value="${siteData.header ? siteData.header.counselingBtnText || 'Book Online Counseling' : 'Book Online Counseling'}" /> 4109 </div> 4110 <button id="btn-save-header" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save Header Settings</button> 4111 </div> 4112 `; 4113 4114 case 'hero': 4115 const h = siteData.hero || {}; 4116 return ` 4117 <div class="admin-section-editor"> 4118 <h3><i class="fa-solid fa-house"></i> Hero Section Settings</h3> 4119 <div class="admin-form-group"> 4120 <label>Top Trust Badge Text</label> 4121 <input type="text" id="admin-hero-badge" value="${h.badge || 'ESTABLISHED 2016 ⢠GOVT. REGD. PVT. LTD.'}" /> 4122 </div> 4123 <div class="admin-form-group"> 4124 <label>Eyebrow Tag</label> 4125 <input type="text" id="admin-hero-eyebrow" value="${h.eyebrow || 'KAVYA GLOBAL NETWORK NEPAL'}" /> 4126 </div> 4127 <div style="display: grid; grid-template-columns: 2fr 1fr 0.5fr 1fr; gap: 12px;"> 4128 <div class="admin-form-group"> 4129 <label>Title Prefix</label> 4130 <input type="text" id="admin-hero-title1" value="${h.titlePart1 || '#1 Brand for Study in '}" /> 4131 </div> 4132 <div class="admin-form-group"> 4133 <label>USA Word</label> 4134 <input type="text" id="admin-hero-usa" value="${h.titleUSA || 'USA'}" /> 4135 </div> 4136 <div class="admin-form-group"> 4137 <label>Separator</label> 4138 <input type="text" id="admin-hero-and" value="${h.titleAnd || ' and '}" /> 4139 </div> 4140 <div class="admin-form-group"> 4141 <label>Australia Word</label> 4142 <input type="text" id="admin-hero-aus" value="${h.titleAustralia || 'Australia'}" /> 4143 </div> 4144 </div> 4145 <div class="admin-form-group"> 4146 <label>Hero Description Paragraph</label> 4147 <textarea id="admin-hero-desc" style="height: 85px;">${h.description || ''}</textarea> 4148 </div> 4149 <div class="admin-form-group"> 4150 <label>Trust Proof Bar Text</label> 4151 <input type="text" id="admin-hero-trust" value="${h.trustText || 'Trusted by 10,000+ Students & Families Across Nepal'}" /> 4152 </div> 4153 <div class="admin-form-group"> 4154 <label>Hero Model Image URL</label> 4155 <input type="text" id="admin-hero-img" value="${h.heroImage || ''}" /> 4156 </div> 4157 4158 <h4 style="margin: 25px 0 10px; color: #004a3e;"><i class="fa-solid fa-graduation-cap"></i> Right Side Test Prep Feature Card</h4> 4159 <div class="admin-form-group"> 4160 <label>PTE / IELTS Card Top Tag</label> 4161 <input type="text" id="admin-hero-pte-tag" value="${h.badgePte || 'Official PTE Academic & IELTS Preparation'}" /> 4162 </div> 4163 <div class="admin-form-group"> 4164 <label>PTE / IELTS Card Title</label> 4165 <input type="text" id="admin-hero-pte-title" value="${h.badgePteTitle || 'Score 79+ in PTE & 7.5+ in IELTS on First Attempt'}" /> 4166 </div> 4167 <div class="admin-form-group"> 4168 <label>PTE / IELTS Card Description</label> 4169 <textarea id="admin-hero-pte-sub" style="height: 60px;">${h.badgePteSub || ''}</textarea> 4170 </div> 4171 <button id="btn-save-hero" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save Hero Section</button> 4172 </div> 4173 `; 4174 4175 case 'counters': 4176 const counters = siteData.counters || []; 4177 return ` 4178 <div class="admin-section-editor"> 4179 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;"> 4180 <h3 style="margin: 0;"><i class="fa-solid fa-chart-simple"></i> Stats Counters</h3> 4181 <button id="btn-add-counter" style="background: #004a3e; color: #fff; border: none; padding: 8px 16px; border-radius: 8px; font-weight: 700; font-size: 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;"> 4182 <i class="fa-solid fa-plus"></i> Add Counter 4183 </button> 4184 </div> 4185 ${counters.map((c, i) => ` 4186 <div style="border: 1px solid #e0e9e7; padding: 15px; border-radius: 10px; margin-bottom: 15px; background: #fafcfb; position: relative;"> 4187 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"> 4188 <h4 style="margin: 0; color: #004a3e;">Counter #${i + 1}</h4> 4189 <button class="btn-delete-counter" data-index="${i}" style="background: #ffebe9; color: #d9381e; border: 1px solid #ffc4c0; padding: 4px 10px; border-radius: 6px; font-size: 11px; font-weight: 700; cursor: pointer;">
4190 <i class="fa-solid fa-trash"></i> Delete 4191 </button> 4192 </div> 4193 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> 4194 <div class="admin-form-group"> 4195 <label>Stat Number (e.g. 100%, 98%, 25+)</label> 4196 <input type="text" id="admin-counter-num-${i}" value="${c.number}" /> 4197 </div> 4198 <div class="admin-form-group"> 4199 <label>Stat Label</label> 4200 <input type="text" id="admin-counter-label-${i}" value="${c.label}" /> 4201 </div> 4202 </div> 4203 </div> 4204 `).join('')} 4205 <button id="btn-save-counters" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save Stats Counters</button> 4206 </div> 4207 `; 4208 4209 case 'about': 4210 const ab = siteData.about || {}; 4211 return ` 4212 <div class="admin-section-editor"> 4213 <h3><i class="fa-solid fa-building-columns"></i> About Us Page Content</h3> 4214 <div class="admin-form-group"> 4215 <label>Page Title</label> 4216 <input type="text" id="admin-about-title" value="${ab.title || 'About Kavya Global Network'}" /> 4217 </div> 4218 <div class="admin-form-group"> 4219 <label>Page Subtitle / Tagline</label> 4220 <input type="text" id="admin-about-sub" value="${ab.subtitle || ''}" /> 4221 </div> 4222 <div class="admin-form-group"> 4223 <label>Story Section Badge</label> 4224 <input type="text" id="admin-about-badge" value="${ab.storyBadge || 'ESTABLISHED 2016 ⢠GOVT. REGD. PVT. LTD.'}" /> 4225 </div> 4226 <div class="admin-form-group"> 4227 <label>Story Main Heading</label> 4228 <input type="text" id="admin-about-story-title" value="${ab.storyTitle || ''}" /> 4229 </div> 4230 <div class="admin-form-group"> 4231 <label>Story Paragraph 1</label> 4232 <textarea id="admin-about-p1" style="height: 90px;">${ab.storyP1 || ''}</textarea> 4233 </div> 4234 <div class="admin-form-group"> 4235 <label>Story Paragraph 2</label> 4236 <textarea id="admin-about-p2" style="height: 90px;">${ab.storyP2 || ''}</textarea> 4237 </div> 4238 <div class="admin-form-group"> 4239 <label>Story Feature Image URL</label> 4240 <input type="text" id="admin-about-img" value="${ab.storyImage || ''}" /> 4241 </div> 4242 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> 4243 <div class="admin-form-group"> 4244 <label>Vision Statement</label> 4245 <textarea id="admin-about-vision" style="height: 80px;">${ab.vision || ''}</textarea> 4246 </div> 4247 <div class="admin-form-group"> 4248 <label>Mission Statement</label> 4249 <textarea id="admin-about-mission" style="height: 80px;">${ab.mission || ''}</textarea> 4250 </div> 4251 </div> 4252 <button id="btn-save-about" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save About Page Content</button> 4253 </div> 4254 `; 4255 4256 case 'director': 4257 const dir = siteData.directorMessage || {}; 4258 return ` 4259 <div class="admin-section-editor"> 4260 <h3><i class="fa-solid fa-user-tie"></i> Director Leadership Message</h3> 4261 <div class="admin-form-group"> 4262 <label>Section Tag</label> 4263 <input type="text" id="admin-dir-tag" value="${dir.tag || 'LEADERSHIP & ETHICAL COUNSELING'}" /> 4264 </div> 4265 <div class="admin-form-group"> 4266 <label>Section Title</label> 4267 <input type="text" id="admin-dir-title" value="${dir.title || 'Empowering Nepalese Students on the Global Stage'}" /> 4268 </div> 4269 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> 4270 <div class="admin-form-group"> 4271 <label>Leader Name</label> 4272 <input type="text" id="admin-dir-name" value="${dir.name || 'Krishna Psd Aryal'}" /> 4273 </div> 4274 <div class="admin-form-group"> 4275 <label>Designation / Role</label> 4276 <input type="text" id="admin-dir-role" value="${dir.role || 'Founder & Managing Director, Kavya Global Network'}" /> 4277 </div> 4278 </div> 4279 <div class="admin-form-group"> 4280 <label>Photo Overlay Badge</label> 4281 <input type="text" id="admin-dir-badge" value="${dir.badge || 'Founder & Managing Director'}" /> 4282 </div> 4283 <div class="admin-form-group"> 4284 <label>Highlight Quote</label> 4285 <textarea id="admin-dir-quote" style="height: 70px;">${dir.quote || ''}</textarea> 4286 </div> 4287 <div class="admin-form-group"> 4288 <label>Detailed Message Paragraph</label> 4289 <textarea id="admin-dir-desc" style="height: 110px;">${dir.description || ''}</textarea> 4290 </div> 4291 <div class="admin-form-group"> 4292 <label>Director Photo Image URL</label> 4293 <input type="text" id="admin-dir-image" value="${dir.image || '/uploads/managing-director-kavya.jpg'}" /> 4294 </div> 4295 <button id="btn-save-director" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save Director Message</button> 4296 </div> 4297 `; 4298 4299 case 'partners': 4300 return ` 4301 <div class="admin-section-editor"> 4302 <h3><i class="fa-solid fa-handshake"></i> Global University Partners Marquee</h3> 4303 <div class="admin-form-group"> 4304 <label>Marquee Section Title</label>
4305 <input type="text" id="admin-partners-title" value="${siteData.partners ? siteData.partners.title : ''}" /> 4306 </div> 4307 4308 <div style="display: flex; justify-content: space-between; align-items: center; margin: 20px 0 10px;"> 4309 <h4 style="color: #004a3e; margin: 0;">University Partners (${siteData.partners ? siteData.partners.logos.length : 0})</h4> 4310 <button id="btn-add-partner-uni" style="background: #004a3e; color: #fff; border: none; padding: 8px 16px; border-radius: 8px; font-weight: 700; font-size: 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;"> 4311 <i class="fa-solid fa-plus"></i> Add Partner University 4312 </button> 4313 </div> 4314 4315 ${(siteData.partners ? siteData.partners.logos : []).map((p, i) => ` 4316 <div style="border: 1px solid #e0e9e7; padding: 15px; border-radius: 10px; margin-bottom: 15px; background: #fafcfb;"> 4317 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"> 4318 <h5 style="margin: 0; color: #004a3e;">Partner #${i + 1}: ${p.name}</h5> 4319 <button class="btn-delete-partner-uni" data-index="${i}" style="background: #ffebe9; color: #d9381e; border: 1px solid #ffc4c0; padding: 4px 10px; border-radius: 6px; font-size: 11px; font-weight: 700; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;"> 4320 <i class="fa-solid fa-trash"></i> Delete 4321 </button> 4322 </div> 4323 <div class="admin-form-group"> 4324 <label>University Name</label> 4325 <input type="text" id="admin-partner-name-${i}" value="${p.name}" /> 4326 </div> 4327 <div class="admin-form-group"> 4328 <label>Location / Country</label> 4329 <input type="text" id="admin-partner-loc-${i}" value="${p.location || ''}" /> 4330 </div> 4331 <div class="admin-form-group"> 4332 <label>Display Badge Text</label> 4333 <input type="text" id="admin-partner-logo-${i}" value="${p.logo}" /> 4334 </div> 4335 <div class="admin-form-group"> 4336 <label>Logo Image URL / Path (e.g. /uploads/logos/vu_hires.png)</label> 4337 <input type="text" id="admin-partner-img-${i}" value="${p.img || ''}" placeholder="/uploads/logos/..." /> 4338 </div> 4339 </div> 4340 `).join('')} 4341 <button id="btn-save-partners" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save Partner Logos</button> 4342 </div> 4343 `; 4344 4345 case 'services': 4346 return ` 4347 <div class="admin-section-editor"> 4348 <h3><i class="fa-solid fa-briefcase"></i> Services Section Settings</h3> 4349 <div class="admin-form-group"> 4350 <label>Section Tag</label> 4351 <input type="text" id="admin-serv-tag" value="${siteData.services.tag}" /> 4352 </div> 4353 <div class="admin-form-group"> 4354 <label>Section Title</label> 4355 <input type="text" id="admin-serv-title" value="${siteData.services.title}" /> 4356 </div> 4357 <div class="admin-form-group"> 4358 <label>Section Description</label> 4359 <textarea id="admin-serv-desc">${siteData.services.description}</textarea> 4360 </div> 4361 4362 <div style="display: flex; justify-content: space-between; align-items: center; margin: 25px 0 15px;"> 4363 <h4 style="color: #004a3e; margin: 0;">Service Cards (${siteData.services.items.length})</h4> 4364 <button id="btn-add-service" style="background: #004a3e; color: #fff; border: none; padding: 8px 16px; border-radius: 8px; font-weight: 700; font-size: 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;"> 4365 <i class="fa-solid fa-plus"></i> Add Service 4366 </button> 4367 </div> 4368 4369 ${siteData.services.items.map((s, i) => ` 4370 <div style="border: 1px solid #e0e9e7; padding: 15px; border-radius: 10px; margin-bottom: 15px; background: #fafcfb;"> 4371 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"> 4372 <h5 style="margin: 0; color: #004a3e;">Service Card #${i + 1}: ${s.title}</h5> 4373 <button class="btn-delete-service" data-index="${i}" style="background: #ffebe9; color: #d9381e; border: 1px solid #ffc4c0; padding: 4px 10px; border-radius: 6px; font-size: 11px; font-weight: 700; cursor: pointer;">
4374 <i class="fa-solid fa-trash"></i> Delete 4375 </button> 4376 </div> 4377 <div class="admin-form-group"> 4378 <label>Service Title</label> 4379 <input type="text" id="admin-serv-item-title-${i}" value="${s.title}" /> 4380 </div> 4381 <div class="admin-form-group"> 4382 <label>Description</label> 4383 <textarea id="admin-serv-item-desc-${i}" style="height: 70px;">${s.description}</textarea> 4384 </div> 4385 </div> 4386 `).join('')} 4387 <button id="btn-save-services" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save Services Section</button> 4388 </div> 4389 `; 4390 4391 case 'destinations': 4392 const destItems = (siteData.destinations && siteData.destinations.items) ? siteData.destinations.items : []; 4393 return ` 4394 <div class="admin-section-editor"> 4395 <h3><i class="fa-solid fa-globe"></i> Destinations Section (Including Germany)</h3> 4396 <div class="admin-form-group"> 4397 <label>Section Tag</label> 4398 <input type="text" id="admin-dest-tag" value="${siteData.destinations.tag || 'GLOBAL STUDY DESTINATIONS'}" /> 4399 </div> 4400 <div class="admin-form-group"> 4401 <label>Section Title</label> 4402 <input type="text" id="admin-dest-title" value="${siteData.destinations.title || 'Top Countries for Your International Academic Degree'}" /> 4403 </div> 4404 4405 <div style="display: flex; justify-content: space-between; align-items: center; margin: 25px 0 15px;"> 4406 <h4 style="color: #004a3e; margin: 0;">Destination Cards (${destItems.length})</h4> 4407 <button id="btn-add-destination" style="background: #004a3e; color: #fff; border: none; padding: 8px 16px; border-radius: 8px; font-weight: 700; font-size: 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;"> 4408 <i class="fa-solid fa-plus"></i> Add Destination 4409 </button> 4410 </div> 4411 4412 ${destItems.map((d, i) => ` 4413 <div style="border: 1px solid #e0e9e7; padding: 16px; border-radius: 12px; margin-bottom: 16px; background: #fafcfb;"> 4414 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;"> 4415 <h5 style="margin: 0; color: #004a3e;"><i class="fa-solid fa-location-dot" style="color: #f9981b;"></i> Destination #${i + 1}: ${d.title}</h5> 4416 <button class="btn-delete-destination" data-index="${i}" style="background: #ffebe9; color: #d9381e; border: 1px solid #ffc4c0; padding: 4px 10px; border-radius: 6px; font-size: 11px; font-weight: 700; cursor: pointer;"> 4417 <i class="fa-solid fa-trash"></i> Delete 4418 </button> 4419 </div> 4420 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;"> 4421 <div class="admin-form-group"> 4422 <label>Destination Title (e.g. Study in Germany)</label> 4423 <input type="text" id="admin-dest-item-title-${i}" value="${d.title}" /> 4424 </div> 4425 <div class="admin-form-group"> 4426 <label>Card Image URL</label> 4427 <input type="text" id="admin-dest-item-img-${i}" value="${d.image}" /> 4428 </div> 4429 </div> 4430 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;"> 4431 <div class="admin-form-group"> 4432 <label>Intake / Feature Badge (e.g. Tuition-Free / Low Tuition)</label> 4433 <input type="text" id="admin-dest-item-badge-${i}" value="${d.badge || ''}" /> 4434 </div> 4435 <div class="admin-form-group"> 4436 <label>Sub-Badge (e.g. German Student Visa)</label> 4437 <input type="text" id="admin-dest-item-subbadge-${i}" value="${d.subBadge || ''}" /> 4438 </div> 4439 </div> 4440 </div> 4441 `).join('')} 4442 <button id="btn-save-destinations" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save Destinations Section</button> 4443 </div> 4444 `; 4445 4446 case 'visaSuccess': 4447 const visa = siteData.visaSuccess || { tag: 'REAL PROOF OF SUCCESS', title: 'Recent Visa Approval Gallery', items: [] }; 4448 return ` 4449 <div class="admin-section-editor"> 4450 <h3><i class="fa-solid fa-passport"></i> Recent Visa Approvals Gallery</h3> 4451 <div class="admin-form-group"> 4452 <label>Section Tag</label> 4453 <input type="text" id="admin-visa-tag" value="${visa.tag || ''}" /> 4454 </div> 4455 <div class="admin-form-group"> 4456 <label>Section Title</label> 4457 <input type="text" id="admin-visa-title" value="${visa.title || ''}" /> 4458 </div> 4459 4460 <div style="display: flex; justify-content: space-between; align-items: center; margin: 25px 0 15px;"> 4461 <h4 style="color: #004a3e; margin: 0;">Student Visa Approvals (${visa.items ? visa.items.length : 0})</h4> 4462 <button id="btn-add-visa" style="background: #004a3e; color: #fff; border: none; padding: 8px 16px; border-radius: 8px; font-weight: 700; font-size: 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;"> 4463 <i class="fa-solid fa-plus"></i> Add Visa Approval 4464 </button> 4465 </div> 4466 4467 ${(visa.items || []).map((v, i) => ` 4468 <div style="border: 1px solid #e0e9e7; padding: 16px; border-radius: 12px; margin-bottom: 16px; background: #fafcfb;"> 4469 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;"> 4470 <h5 style="margin: 0; color: #004a3e;">Approval #${i + 1}: ${v.name}</h5> 4471 <button class="btn-delete-visa" data-index="${i}" style="background: #ffebe9; color: #d9381e; border: 1px solid #ffc4c0; padding: 4px 10px; border-radius: 6px; font-size: 11px; font-weight: 700; cursor: pointer;">
4472 <i class="fa-solid fa-trash"></i> Delete 4473 </button> 4474 </div> 4475 <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px;"> 4476 <div class="admin-form-group"> 4477 <label>Student Name</label> 4478 <input type="text" id="admin-visa-name-${i}" value="${v.name}" /> 4479 </div> 4480 <div class="admin-form-group"> 4481 <label>Target Country</label> 4482 <input type="text" id="admin-visa-country-${i}" value="${v.country}" /> 4483 </div> 4484 <div class="admin-form-group"> 4485 <label>Grant Status Badge</label> 4486 <input type="text" id="admin-visa-badge-${i}" value="${v.badge}" /> 4487 </div> 4488 </div> 4489 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;"> 4490 <div class="admin-form-group"> 4491 <label>University / Institution</label> 4492 <input type="text" id="admin-visa-uni-${i}" value="${v.university || ''}" /> 4493 </div> 4494 <div class="admin-form-group"> 4495 <label>Visa Approval Photo / Letter URL</label> 4496 <input type="text" id="admin-visa-photo-${i}" value="${v.photo}" /> 4497 </div> 4498 </div> 4499 </div> 4500 `).join('')} 4501 <button id="btn-save-visa" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save Visa Gallery</button> 4502 </div> 4503 `; 4504 4505 case 'testPrep': 4506 return ` 4507 <div class="admin-section-editor"> 4508 <h3><i class="fa-solid fa-pen-to-square"></i> Test Prep & Mock Form Settings</h3> 4509 <div class="admin-form-group"> 4510 <label>Section Tag</label> 4511 <input type="text" id="admin-prep-tag" value="${siteData.testPrep.tag}" /> 4512 </div> 4513 <div class="admin-form-group"> 4514 <label>Section Title</label> 4515 <input type="text" id="admin-prep-title" value="${siteData.testPrep.title}" /> 4516 </div> 4517 <div class="admin-form-group"> 4518 <label>Section Description</label> 4519 <textarea id="admin-prep-desc" style="height: 85px;">${siteData.testPrep.description}</textarea> 4520 </div> 4521 <div class="admin-form-group"> 4522 <label>Mock Test Form Title</label> 4523 <input type="text" id="admin-prep-formtitle" value="${siteData.testPrep.formTitle}" /> 4524 </div> 4525 <div class="admin-form-group"> 4526 <label>Mock Test Form Subtitle</label> 4527 <input type="text" id="admin-prep-formsub" value="${siteData.testPrep.formSub}" /> 4528 </div> 4529 <button id="btn-save-testprep" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save Test Prep Section</button> 4530 </div> 4531 `; 4532 4533 case 'accreditations': 4534 return ` 4535 <div class="admin-section-editor"> 4536 <h3><i class="fa-solid fa-award"></i> Accreditations & Certifications Settings</h3> 4537 <div class="admin-form-group"> 4538 <label>Section Tag</label> 4539 <input type="text" id="admin-accred-tag" value="${siteData.accreditations ? siteData.accreditations.tag : ''}" /> 4540 </div> 4541 <div class="admin-form-group"> 4542 <label>Section Title</label> 4543 <input type="text" id="admin-accred-title" value="${siteData.accreditations ? siteData.accreditations.title : ''}" /> 4544 </div> 4545 <div class="admin-form-group"> 4546 <label>Section Description</label> 4547 <textarea id="admin-accred-desc">${siteData.accreditations ? siteData.accreditations.description : ''}</textarea> 4548 </div> 4549 4550 <div style="display: flex; justify-content: space-between; align-items: center; margin: 20px 0 10px;"> 4551 <h4 style="color: #004a3e; margin: 0;">Certification Badges (${siteData.accreditations ? siteData.accreditations.items.length : 0})</h4> 4552 <button id="btn-add-accred" style="background: #004a3e; color: #fff; border: none; padding: 8px 16px; border-radius: 8px; font-weight: 700; font-size: 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;"> 4553 <i class="fa-solid fa-plus"></i> Add Certificate Badge 4554 </button> 4555 </div> 4556 4557 ${(siteData.accreditations ? siteData.accreditations.items : []).map((a, i) => ` 4558 <div style="border: 1px solid #e0e9e7; padding: 15px; border-radius: 10px; margin-bottom: 15px; background: #fafcfb; position: relative;"> 4559 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"> 4560 <h5 style="margin: 0; color: #004a3e;">Certificate #${i + 1}: ${a.title}</h5> 4561 <button class="btn-delete-accred" data-index="${i}" style="background: #ffebe9; color: #d9381e; border: 1px solid #ffc4c0; padding: 4px 10px; border-radius: 6px; font-size: 11px; font-weight: 700; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;">
4562 <i class="fa-solid fa-trash"></i> Delete 4563 </button> 4564 </div> 4565 <div class="admin-form-group"> 4566 <label>Title</label> 4567 <input type="text" id="admin-accred-item-title-${i}" value="${a.title}" /> 4568 </div> 4569 <div class="admin-form-group"> 4570 <label>Subtitle / Governing Body</label> 4571 <input type="text" id="admin-accred-item-sub-${i}" value="${a.subtitle}" /> 4572 </div> 4573 <div class="admin-form-group"> 4574 <label>Top Badge Text</label> 4575 <input type="text" id="admin-accred-item-badge-${i}" value="${a.badge}" /> 4576 </div> 4577 </div> 4578 `).join('')} 4579 <button id="btn-save-accreditations" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save Accreditations Section</button> 4580 </div> 4581 `; 4582 4583 case 'testimonials': 4584 return ` 4585 <div class="admin-section-editor"> 4586 <h3><i class="fa-brands fa-google" style="color: #4285F4;"></i> Google Reviews & Student Testimonials</h3> 4587 <div class="admin-form-group"> 4588 <label>Section Tag</label> 4589 <input type="text" id="admin-testi-tag" value="${siteData.testimonials.tag || 'REAL STUDENT EXPERIENCES'}" /> 4590 </div> 4591 <div class="admin-form-group"> 4592 <label>Section Title</label> 4593 <input type="text" id="admin-testi-title" value="${siteData.testimonials.title || 'Student Success Stories'}" /> 4594 </div> 4595 <div class="admin-form-group"> 4596 <label>Section Subtitle</label> 4597 <input type="text" id="admin-testi-sub" value="${siteData.testimonials.subtitle || ''}" /> 4598 </div> 4599 4600 <h4 style="margin: 20px 0 10px; color: #004a3e;"><i class="fa-solid fa-chart-line"></i> Google Business Profile Stats</h4> 4601 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> 4602 <div class="admin-form-group"> 4603 <label>Google Star Rating</label> 4604 <input type="text" id="admin-testi-rating" value="${siteData.testimonials.googleRating || '4.9'}" placeholder="e.g. 4.9" /> 4605 </div> 4606 <div class="admin-form-group"> 4607 <label>Google Review Count</label> 4608 <input type="text" id="admin-testi-count" value="${siteData.testimonials.googleReviewCount || '194'}" placeholder="e.g. 194" /> 4609 </div> 4610 </div> 4611 <div class="admin-form-group"> 4612 <label>Google Maps Search / Profile Link</label> 4613 <input type="text" id="admin-testi-mapurl" value="${siteData.testimonials.googleMapsUrl || 'https://www.google.com/search?q=Kavya+Global+Network'}" /> 4614 </div> 4615 4616 <div style="display: flex; justify-content: space-between; align-items: center; margin: 25px 0 15px;"> 4617 <h4 style="color: #004a3e; margin: 0;"><i class="fa-solid fa-comments"></i> Student Google Reviews (${siteData.testimonials.reviews.length})</h4> 4618 <button id="btn-add-testimonial" style="background: #004a3e; color: #fff; border: none; padding: 8px 16px; border-radius: 8px; font-weight: 700; font-size: 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;"> 4619 <i class="fa-solid fa-plus"></i> Add Google Review 4620 </button> 4621 </div> 4622 4623 ${siteData.testimonials.reviews.map((r, i) => ` 4624 <div style="border: 1px solid #e0e9e7; padding: 16px; border-radius: 12px; margin-bottom: 16px; background: #fafcfb; position: relative;"> 4625 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;"> 4626 <h5 style="margin: 0; color: #004a3e; display: flex; align-items: center; gap: 6px;"> 4627 <i class="fa-brands fa-google" style="color: #4285F4; font-size: 13px;"></i> Review #${i + 1}: ${r.name} 4628 </h5> 4629 <button class="btn-delete-testimonial" data-index="${i}" style="background: #ffebe9; color: #d9381e; border: 1px solid #ffc4c0; padding: 4px 10px; border-radius: 6px; font-size: 11px; font-weight: 700; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;">
4630 <i class="fa-solid fa-trash"></i> Delete 4631 </button> 4632 </div> 4633 <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px;"> 4634 <div class="admin-form-group"> 4635 <label>Student Name</label> 4636 <input type="text" id="admin-testi-name-${i}" value="${r.name}" /> 4637 </div> 4638 <div class="admin-form-group"> 4639 <label>Destination / Course</label> 4640 <input type="text" id="admin-testi-country-${i}" value="${r.country}" /> 4641 </div> 4642 <div class="admin-form-group"> 4643 <label>Relative Date</label> 4644 <input type="text" id="admin-testi-date-${i}" value="${r.date || '2 weeks ago'}" placeholder="e.g. 2 weeks ago" /> 4645 </div> 4646 </div> 4647 <div class="admin-form-group"> 4648 <label>Review Text</label> 4649 <textarea id="admin-testi-review-${i}" style="height: 70px;">${r.review}</textarea> 4650 </div> 4651 <div class="admin-form-group"> 4652 <label>Avatar Photo URL</label> 4653 <input type="text" id="admin-testi-avatar-${i}" value="${r.avatar}" /> 4654 </div> 4655 </div> 4656 `).join('')} 4657 <button id="btn-save-testimonials" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save Google Reviews Settings</button> 4658 </div> 4659 `; 4660 4661 case 'faqs': 4662 const faqsData = siteData.faqs || { tag: 'FREQUENTLY ASKED QUESTIONS', title: 'Everything You Need to Know About Studying Abroad', description: '', items: [] }; 4663 return ` 4664 <div class="admin-section-editor"> 4665 <h3><i class="fa-solid fa-circle-question"></i> FAQs Accordion Settings</h3> 4666 <div class="admin-form-group"> 4667 <label>Section Tag</label> 4668 <input type="text" id="admin-faq-tag" value="${faqsData.tag || ''}" /> 4669 </div> 4670 <div class="admin-form-group"> 4671 <label>Section Title</label> 4672 <input type="text" id="admin-faq-title" value="${faqsData.title || ''}" /> 4673 </div> 4674 <div class="admin-form-group"> 4675 <label>Section Description</label> 4676 <textarea id="admin-faq-desc" style="height: 65px;">${faqsData.description || ''}</textarea> 4677 </div> 4678 4679 <div style="display: flex; justify-content: space-between; align-items: center; margin: 25px 0 15px;"> 4680 <h4 style="color: #004a3e; margin: 0;">FAQ Accordion Items (${faqsData.items ? faqsData.items.length : 0})</h4> 4681 <button id="btn-add-faq" style="background: #004a3e; color: #fff; border: none; padding: 8px 16px; border-radius: 8px; font-weight: 700; font-size: 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;"> 4682 <i class="fa-solid fa-plus"></i> Add New FAQ 4683 </button> 4684 </div> 4685 4686 ${(faqsData.items || []).map((faq, i) => ` 4687 <div style="border: 1px solid #e0e9e7; padding: 16px; border-radius: 12px; margin-bottom: 16px; background: #fafcfb;"> 4688 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;"> 4689 <h5 style="margin: 0; color: #004a3e;">FAQ #${i + 1}</h5> 4690 <button class="btn-delete-faq" data-index="${i}" style="background: #ffebe9; color: #d9381e; border: 1px solid #ffc4c0; padding: 4px 10px; border-radius: 6px; font-size: 11px; font-weight: 700; cursor: pointer;"> 4691 <i class="fa-solid fa-trash"></i> Delete 4692 </button> 4693 </div> 4694 <div class="admin-form-group"> 4695 <label>Question</label> 4696 <input type="text" id="admin-faq-q-${i}" value="${faq.question}" /> 4697 </div> 4698 <div class="admin-form-group"> 4699 <label>Answer</label> 4700 <textarea id="admin-faq-a-${i}" style="height: 80px;">${faq.answer}</textarea> 4701 </div> 4702 </div> 4703 `).join('')} 4704 <button id="btn-save-faqs" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save FAQs Accordion</button> 4705 </div> 4706 `; 4707 4708 case 'footer': 4709 const ft = siteData.footer || {}; 4710 const qLinks = ft.quickLinks || []; 4711 const cLinks = ft.countries || []; 4712 return ` 4713 <div class="admin-section-editor"> 4714 <h3><i class="fa-solid fa-shoe-prints"></i> Footer Section Settings</h3> 4715 <div class="admin-form-group"> 4716 <label>Footer About Paragraph</label> 4717 <textarea id="admin-footer-about" style="height: 80px;">${ft.aboutText || ''}</textarea> 4718 </div> 4719 <div class="admin-form-group"> 4720 <label>Copyright Notice</label> 4721 <input type="text" id="admin-footer-copy" value="${ft.copyright || '© 2026 Kavya Global Network. All Rights Reserved.'}" /> 4722 </div> 4723 4724 <h4 style="margin: 20px 0 10px; color: #004a3e;"><i class="fa-solid fa-share-nodes"></i> Social Media Links</h4> 4725 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;"> 4726 <div class="admin-form-group"> 4727 <label>Facebook URL</label> 4728 <input type="text" id="admin-social-fb" value="${ft.social ? ft.s
4728ocial.facebook || '' : ''}" /> 4729 </div> 4730 <div class="admin-form-group"> 4731 <label>Instagram URL</label> 4732 <input type="text" id="admin-social-insta" value="${ft.social ? ft.social.instagram || '' : ''}" /> 4733 </div> 4734 <div class="admin-form-group"> 4735 <label>LinkedIn URL</label> 4736 <input type="text" id="admin-social-linkedin" value="${ft.social ? ft.social.linkedin || '' : ''}" /> 4737 </div> 4738 <div class="admin-form-group"> 4739 <label>YouTube URL</label> 4740 <input type="text" id="admin-social-yt" value="${ft.social ? ft.social.youtube || '' : ''}" /> 4741 </div> 4742 </div> 4743 4744 <div style="display: flex; justify-content: space-between; align-items: center; margin: 25px 0 10px;"> 4745 <h4 style="color: #004a3e; margin: 0;">Footer Quick Links (${qLinks.length})</h4> 4746 <button id="btn-add-quicklink" style="background: #004a3e; color: #fff; border: none; padding: 6px 14px; border-radius: 8px; font-weight: 700; font-size: 11.5px; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;"> 4747 <i class="fa-solid fa-plus"></i> Add Link 4748 </button> 4749 </div> 4750 ${qLinks.map((l, i) => ` 4751 <div style="display: flex; gap: 10px; align-items: center; margin-bottom: 10px;"> 4752 <input type="text" id="admin-footer-ql-name-${i}" value="${l.name}" placeholder="Link Name" style="flex: 1;" /> 4753 <input type="text" id="admin-footer-ql-url-${i}" value="${l.url}" placeholder="URL / Anchor" style="flex: 1;" /> 4754 <button class="btn-delete-quicklink" data-index="${i}" style="background: #ffebe9; color: #d9381e; border: 1px solid #ffc4c0; padding: 8px 12px; border-radius: 6px; font-size: 11px; cursor: pointer;"> 4755 <i class="fa-solid fa-trash"></i> 4756 </button> 4757 </div> 4758 `).join('')} 4759 4760 <div style="display: flex; justify-content: space-between; align-items: center; margin: 25px 0 10px;"> 4761 <h4 style="color: #004a3e; margin: 0;">Footer Country Links (${cLinks.length})</h4> 4762 <button id="btn-add-countrylink" style="background: #004a3e; color: #fff; border: none; padding: 6px 14px; border-radius: 8px; font-weight: 700; font-size: 11.5px; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;"> 4763 <i class="fa-solid fa-plus"></i> Add Country Link 4764 </button> 4765 </div> 4766 ${cLinks.map((c, i) => ` 4767 <div style="display: flex; gap: 10px; align-items: center; margin-bottom: 10px;"> 4768 <input type="text" id="admin-footer-c-name-${i}" value="${c.name}" placeholder="Country Title" style="flex: 1;" /> 4769 <input type="text" id="admin-footer-c-url-${i}" value="${c.url}" placeholder="URL / Anchor" style="flex: 1;" /> 4770 <button class="btn-delete-countrylink" data-index="${i}" style="background: #ffebe9; color: #d9381e; border: 1px solid #ffc4c0; padding: 8px 12px; border-radius: 6px; font-size: 11px; cursor: pointer;"> 4771 <i class="fa-solid fa-trash"></i> 4772 </button> 4773 </div> 4774 `).join('')} 4775 4776 <button id="btn-save-footer" class="btn-save-admin" style="margin-top: 15px;"><i class="fa-solid fa-save"></i> Save Footer Settings</button> 4777 </div> 4778 `; 4779 4780 case 'general': 4781 return ` 4782 <div class="admin-section-editor"> 4783 <h3><i class="fa-solid fa-sliders"></i> General & Contact Settings</h3> 4784 <div class="admin-form-group"> 4785 <label>Site Name</label> 4786 <input type="text" id="admin-gen-sitename" value="${siteData.general.siteName}" /> 4787 </div> 4788 <div class="admin-form-group"> 4789 <label>Email Address</label> 4790 <input type="text" id="admin-gen-email" value="${siteData.general.email}" /> 4791 </div> 4792 <div class="admin-form-group"> 4793 <label>Landline Phone</label> 4794 <input type="text" id="admin-gen-phone" value="${siteData.general.ph
4794one}" /> 4795 </div> 4796 <div class="admin-form-group"> 4797 <label>Mobile / WhatsApp</label> 4798 <input type="text" id="admin-gen-mobile" value="${siteData.general.mobilePhone}" /> 4799 </div> 4800 <div class="admin-form-group"> 4801 <label>Website Layout Mode</label> 4802 <select id="admin-gen-layout"> 4803 <option value="full-width" ${siteData.general.layoutMode === 'full-width' ? 'selected' : ''}>Full Width (Fluid Edge-to-Edge)</option> 4804 <option value="boxed" ${siteData.general.layoutMode === 'boxed' ? 'selected' : ''}>Boxed Layout (1240px Centered)</option> 4805 </select> 4806 </div> 4807 <div class="admin-form-group"> 4808 <label>Office Address</label> 4809 <input type="text" id="admin-gen-address" value="${siteData.general.address}" /> 4810 </div> 4811 <div class="admin-form-group"> 4812 <label>Footer About Text</label> 4813 <textarea id="admin-gen-footer-about">${siteData.footer ? siteData.footer.aboutText : ''}</textarea> 4814 </div> 4815 <button id="btn-save-gen" class="btn-save-admin"><i class="fa-solid fa-save"></i> Save General Settings</button> 4816 4817 <hr style="margin: 30px 0; border: none; border-top: 1px solid #e0e9e7;" /> 4818 <h3 style="color: #004a3e;"><i class="fa-solid fa-key"></i> Security â Change Admin Password</h3> 4819 <div id="change-pass-msg" style="margin-bottom: 14px; font-weight: 600; font-size: 13px;"></div> 4820 <div class="admin-form-group"> 4821 <label>Current Password</label> 4822 <input type="password" id="admin-curr-pass" placeholder="Enter current password" /> 4823 </div> 4824 <div class="admin-form-group"> 4825 <label>New Password</label> 4826 <input type="password" id="admin-new-pass" placeholder="Enter new password (min 4 characters)" /> 4827 </div> 4828 <button id="btn-save-new-pass" class="btn-save-admin" style="background: #28a745;"><i class="fa-solid fa-shield-halved"></i> Update Admin Password</button> 4829 </div> 4830 `; 4831 4832 case 'leads': 4833 const mockCount = formSubmissions.filter(s => (s.source && s.source.includes('Mock')) || s.testType).length; 4834 const counselCount = formSubmissions.filter(s => (s.source && s.source.includes('Counseling')) || s.country || (s.address && s.address.includes('Counseling'))).length; 4835 4836 const filteredLeads = formSubmissions.filter(s => { 4837 const isMock = (s.source && s.source.includes('Mock')) || s.testType; 4838 const isCounsel = (s.source && s.source.includes('Counseling')) || s.country || (s.address && s.address.includes('Counseling')); 4839 if (activeLeadFilter === 'mock') return isMock; 4840 if (activeLeadFilter === 'counseling') return isCounsel; 4841 return true; 4842 }); 4843 4844 return ` 4845 <div class="admin-section-editor"> 4846 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;"> 4847 <h3 style="color: #00332a;"><i class="fa-solid fa-users"></i> Lead Management & Registrations</h3> 4848 </div> 4849 4850 <!-- KPI Counters Row --> 4851 <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin-bottom: 25px;"> 4852 <div style="background: #ffffff; border: 1px solid #d0dfdc; border-radius: 12px; padding: 18px 20px; box-shadow: 0 4px 12px rgba(0,0,0,0.03);"> 4853 <span style="font-size: 11px; font-weight: 800; color: #666; text-transform: uppercase; letter-spacing: 0.5px;">Total Submissions</span> 4854 <div style="font-size: 26px; font-weight: 800; color: #00332a; margin-top: 4px;">${formSubmissions.length}</div> 4855 </div> 4856 <div style="background: #ffffff; border: 1px solid #cce5e0; border-radius: 12px; padding: 18px 20px; box-shadow: 0 4px 12px rgba(0,0,0,0.03);"> 4857 <span style="font-size: 11px; font-weight: 800; color: #004a3e; text-transform: uppercase; letter-spacing: 0.5px;">Mock Test Bookings</span> 4858 <div style="font-size: 26px; font-weight: 800; color: #004a3e; margin-top: 4px;">${mockCount}</div> 4859 </div> 4860 <div style="background: #ffffff; border: 1px solid #e1d4f5; border-radius: 12px; padding: 18px 20px; box-shadow: 0 4px 12px rgba(0,0,0,0.03);">
4861 <span style="font-size: 11px; font-weight: 800; color: #5c27b0; text-transform: uppercase; letter-spacing: 0.5px;">Online Counseling</span> 4862 <div style="font-size: 26px; font-weight: 800; color: #5c27b0; margin-top: 4px;">${counselCount}</div> 4863 </div> 4864 </div> 4865 4866 <!-- Filter Tabs --> 4867 <div style="display: flex; gap: 10px; margin-bottom: 20px;"> 4868 <button class="lead-filter-tab ${activeLeadFilter === 'all' ? 'active' : ''}" data-filter="all"> 4869 All Leads (${formSubmissions.length}) 4870 </button> 4871 <button class="lead-filter-tab ${activeLeadFilter === 'mock' ? 'active' : ''}" data-filter="mock"> 4872 <i class="fa-solid fa-pen-to-square"></i> Mock Test Bookings (${mockCount}) 4873 </button> 4874 <button class="lead-filter-tab ${activeLeadFilter === 'counseling' ? 'active' : ''}" data-filter="counseling"> 4875 <i class="fa-solid fa-headset"></i> Online Counseling (${counselCount}) 4876 </button> 4877 </div> 4878 4879 ${filteredLeads.length === 0 ? ` 4880 <div style="background: #fff; padding: 40px; text-align: center; border-radius: 12px; border: 1px solid #e0e9e7; color: #888;"> 4881 <i class="fa-solid fa-inbox" style="font-size: 36px; margin-bottom: 12px; color: #ccc;"></i> 4882 <p>No lead submissions found for this filter category.</p> 4883 </div> 4884 ` : ` 4885 <div style="background: #fff; border-radius: 12px; border: 1px solid #e0e9e7; overflow: hidden; box-shadow: 0 4px 16px rgba(0,0,0,0.03);"> 4886 <table class="leads-table"> 4887 <thead> 4888 <tr> 4889 <th>Source & Category</th> 4890 <th>Student Contact</th> 4891 <th>Subject / Target</th> 4892 <th>Appointment Slot & Notes</th> 4893 <th>Submitted Date</th> 4894 <th style="width: 70px; text-align: center;">Action</th> 4895 </tr> 4896 </thead> 4897 <tbody> 4898 ${filteredLeads.map(sub => { 4899 const isMock = (sub.source && sub.source.includes('Mock')) || sub.testType; 4900 const sourceLabel = sub.source || (isMock ? 'Mock Test Registration' : 'Online Counseling Booking'); 4901 const categoryLabel = sub.category || sub.testType || sub.country || 'General Inquiry'; 4902 const cleanPhone = (sub.phone || '').replace(/[^0-9+]/g, ''); 4903 4904 return ` 4905 <tr> 4906 <td> 4907 <div style="display: flex; flex-direction: column; gap: 6px;"> 4908 <span class="${isMock ? 'badge-source-mock' : 'badge-source-counsel'}"> 4909 <i class="fa-solid ${isMock ? 'fa-file-lines' : 'fa-video'}"></i> ${sourceLabel} 4910 </span> 4911 </div> 4912 </td> 4913 <td> 4914 <div style="font-weight: 800; color: #00332a; font-size: 14px;">${sub.name}</div> 4915 <div style="font-size: 12px; color: #555; margin-top: 3px;"> 4916 <a href="mailto:${sub.email}" style="color: #006051; text-decoration: none;"><i class="fa-regular fa-envelope"></i> ${sub.email}</a> 4917 </div> 4918 <div style="font-size: 12px; color: #555; margin-top: 2px;"> 4919 <a href="https://wa.me/${cleanPhone}" target="_blank" style="color: #25d366; text-decoration: none; font-weight: 700;"> 4920 <i class="fa-brands fa-whatsapp"></i> ${sub.phone} 4921 </a> 4922 </div> 4923 </td> 4924 <td> 4925 <span class="badge-category">${categoryLabel}</span> 4926 ${sub.address ? `<div style="font-size: 11.5px; color: #666; margin-top: 5px;">${sub.address}</div>` : ''} 4927 </td> 4928 <td> 4929 ${sub.date || sub.timeSlot ? ` 4930 <div style="font-size: 12.5px; font-weight: 700; color: #333;"> 4931 <i class="fa-regular fa-clock" style="color: #004a3e;"></i> ${sub.date || 'Flexible'} | ${sub.timeSlot || 'Anytime'} 4932 </div> 4933 ` : ''} 4934 ${sub.notes ? `<div style="font-size: 12px; color: #666; font-style: italic; margin-top: 4px;">"${sub.notes}"</div>` : ''} 4935 </td> 4936 <td style="font-size: 12px; color: #666;"> 4937 ${new Date(sub.createdAt).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })} 4938 </td> 4939 <td style="text-align: center;"> 4940 <button class="btn-delete-lead" data-id="${sub.id}" style="background: rgba(220, 53, 69, 0.1); color: #dc3545; border: 1px solid rgba(220, 53, 69, 0.2); width: 32px; height: 32px; border-radius: 6px; cursor: pointer; transition: all 0.2s ease;" title="Delete Lead">
4941 <i class="fa-solid fa-trash-can"></i> 4942 </button> 4943 </td> 4944 </tr> 4945 `; 4946 }).join('')} 4947 </tbody> 4948 </table> 4949 </div> 4950 `} 4951 </div> 4952 `; 4953 4954 case 'partnerApps': 4955 const pendingCount = partnerApps.filter(a => a.status === 'pending').length; 4956 const approvedCount = partnerApps.filter(a => a.status === 'approved').length; 4957 const rejectedCount = partnerApps.filter(a => a.status === 'rejected').length; 4958 4959 const filteredPartners = partnerApps.filter(app => { 4960 const q = (partnerSearchQuery || '').toLowerCase().trim(); 4961 const matchQuery = !q || 4962 (app.name && app.name.toLowerCase().includes(q)) || 4963 (app.company && app.company.toLowerCase().includes(q)) || 4964 (app.email && app.email.toLowerCase().includes(q)) || 4965 (app.phone && app.phone.toLowerCase().includes(q)) || 4966 (app.partnerCode && app.partnerCode.toLowerCase().includes(q)) || 4967 (app.id && app.id.toLowerCase().includes(q)); 4968 4969 const matchType = partnerTypeFilter === 'all' || app.partnerType === partnerTypeFilter; 4970 const matchStatus = partnerStatusFilter === 'all' || app.status === partnerStatusFilter; 4971 return matchQuery && matchType && matchStatus; 4972 }); 4973 4974 return ` 4975 <div class="admin-section-editor"> 4976 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 12px;"> 4977 <div> 4978 <h3 style="color: #00332a; margin: 0;"><i class="fa-solid fa-handshake-angle"></i> B2B Partner Directory & Access Control</h3> 4979 <p style="color: #666; font-size: 13px; margin-top: 4px; margin-bottom: 0;">Manage registered education partners, assign custom secure dispatch IDs, and share access credentials.</p> 4980 </div> 4981 <div style="display: flex; gap: 10px; align-items: center;"> 4982 <button id="btn-admin-add-partner" style="background: linear-gradient(135deg, #004a3e, #006b5b); color: #fff; border: none; padding: 9px 18px; border-radius: 8px; font-size: 13px; font-weight: 700; cursor: pointer; display: flex; align-items: center; gap: 7px; box-shadow: 0 4px 12px rgba(0,74,62,0.25);"> 4983 <i class="fa-solid fa-plus-circle"></i> + Add Partner & Assign ID 4984 </button> 4985 <button onclick="loadPartnerApps().then(renderApp)" style="background: #ffffff; color: #004a3e; border: 1px solid #cce5e0; padding: 9px 14px; border-radius: 8px; font-size: 12.5px; cursor: pointer; display: flex; align-items: center; gap: 6px; font-weight: 600;"> 4986 <i class="fa-solid fa-rotate"></i> Refresh 4987 </button> 4988 </div> 4989 </div> 4990 4991 <!-- KPI Counters Row --> 4992 <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px; margin-bottom: 25px;"> 4993 <div style="background: #ffffff; border: 1px solid #d0dfdc; border-radius: 12px; padding: 18px 20px; box-shadow: 0 4px 12px rgba(0,0,0,0.03);"> 4994 <span style="font-size: 11px; font-weight: 800; color: #666; text-transform: uppercase; letter-spacing: 0.5px;">Total Applications</span> 4995 <div style="font-size: 26px; font-weight: 800; color: #00332a; margin-top: 4px;">${partnerApps.length}</div> 4996 </div> 4997 <div style="background: #ffffff; border: 1px solid #ffe8cc; border-radius: 12px; padding: 18px 20px; box-shadow: 0 4px 12px rgba(0,0,0,0.03);"> 4998 <span style="font-size: 11px; font-weight: 800; color: #d97706; text-transform: uppercase; letter-spacing: 0.5px;">Pending Review</span> 4999 <div style="font-size: 26px; font-weight: 800; color: #d97706; margin-top: 4px;">${pendingCount}</div> 5000 </div> 5001 <div style="background: #ffffff; border: 1px solid #cce5e0; border-radius: 12px; padding: 18px 20px; box-shadow: 0 4px 12px rgba(0,0,0,0.03);">
5002 <span style="font-size: 11px; font-weight: 800; color: #004a3e; text-transform: uppercase; letter-spacing: 0.5px;">Approved Partners</span> 5003 <div style="font-size: 26px; font-weight: 800; color: #004a3e; margin-top: 4px;">${approvedCount}</div> 5004 </div> 5005 <div style="background: #ffffff; border: 1px solid #fee2e2; border-radius: 12px; padding: 18px 20px; box-shadow: 0 4px 12px rgba(0,0,0,0.03);"> 5006 <span style="font-size: 11px; font-weight: 800; color: #dc2626; text-transform: uppercase; letter-spacing: 0.5px;">Declined</span> 5007 <div style="font-size: 26px; font-weight: 800; color: #dc2626; margin-top: 4px;">${rejectedCount}</div> 5008 </div> 5009 </div> 5010 5011 <!-- Search and Filter Bar --> 5012 <div style="background: #fff; border: 1px solid #dbe7e4; border-radius: 10px; padding: 12px 16px; margin-bottom: 20px; display: flex; gap: 12px; align-items: center; flex-wrap: wrap;"> 5013 <div style="flex: 1; min-width: 220px; position: relative;"> 5014 <i class="fa-solid fa-magnifying-glass" style="position: absolute; left: 12px; top: 11px; color: #94a3b8;"></i> 5015 <input type="text" id="partner-search-input" value="${partnerSearchQuery || ''}" placeholder="Search by Partner Name, Agency, Email, or Assigned ID..." style="width: 100%; padding: 8px 12px 8px 34px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; outline: none; box-sizing: border-box;" /> 5016 </div> 5017 <div style="display: flex; gap: 8px; align-items: center;"> 5018 <select id="partner-type-filter" style="padding: 8px 12px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 12.5px; color: #334155; background: #fff; cursor: pointer;"> 5019 <option value="all" ${partnerTypeFilter === 'all' ? 'selected' : ''}>All Partner Types</option> 5020 <option value="sub-agent" ${partnerTypeFilter === 'sub-agent' ? 'selected' : ''}>Sub-Agents</option> 5021 <option value="university" ${partnerTypeFilter === 'university' ? 'selected' : ''}>Universities / Colleges</option> 5022 </select> 5023 <select id="partner-status-filter" style="padding: 8px 12px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 12.5px; color: #334155; background: #fff; cursor: pointer;"> 5024 <option value="all" ${partnerStatusFilter === 'all' ? 'selected' : ''}>All Statuses</option> 5025 <option value="approved" ${partnerStatusFilter === 'approved' ? 'selected' : ''}>Approved Only</option> 5026 <option value="pending" ${partnerStatusFilter === 'pending' ? 'selected' : ''}>Pending Review</option> 5027 <option value="rejected" ${partnerStatusFilter === 'rejected' ? 'selected' : ''}>Declined</option> 5028 </select> 5029 ${(partnerSearchQuery || partnerTypeFilter !== 'all' || partnerStatusFilter !== 'all') ? ` 5030 <button id="btn-clear-partner-filters" style="background: #f1f5f9; color: #475569; border: 1px solid #cbd5e1; padding: 7px 12px; border-radius: 6px; font-size: 12px; cursor: pointer; display: flex; align-items: center; gap: 4px;"> 5031 <i class="fa-solid fa-xmark"></i> Clear 5032 </button> 5033 ` : ''} 5034 </div> 5035 </div> 5036 5037 ${filteredPartners.length === 0 ? ` 5038 <div style="background: #fff; padding: 40px; text-align: center; border-radius: 12px; border: 1px solid #e0e9e7; color: #888;"> 5039 <i class="fa-solid fa-handshake" style="font-size: 36px; margin-bottom: 12px; color: #ccc;"></i> 5040 <p>${partnerApps.length === 0 ? 'No partner applications received yet.' : 'No partner records matching your search filters.'}</p> 5041 <button id="btn-admin-add-partner-empty" style="margin-top: 10px; background: #004a3e; color: #fff; border: none; padding: 8px 16px; border-radius: 6px; font-size: 12.5px; font-weight: 700; cursor: pointer;"> 5042 + Add First Partner & Assign ID 5043 </button> 5044 </div> 5045 ` : ` 5046 <div style="background: #fff; border-radius: 12px; border: 1px solid #e0e9e7; overflow: hidden; box-shadow: 0 4px 16px rgba(0,0,0,0.03);"> 5047 <table class="leads-table"> 5048 <thead> 5049 <tr> 5050 <th style="min-width: 170px;">Partner ID & Type</th> 5051 <th style="min-width: 190px;">Contact Person</th> 5052 <th style="min-width: 180px;">Agency / Location</th> 5053 <th style="min-width: 170px;">
5053Details & Volume</th> 5054 <th>Applied Date</th> 5055 <th style="width: 170px; text-align: center;">Actions & Dispatch</th> 5056 </tr> 5057 </thead> 5058 <tbody> 5059 ${filteredPartners.map(app => { 5060 const isSubAgent = app.partnerType === 'sub-agent'; 5061 const cleanPhone = (app.phone || '').replace(/[^0-9+]/g, ''); 5062 const statusColor = app.status === 'approved' ? '#16a34a' : (app.status === 'rejected' ? '#dc2626' : '#d97706'); 5063 const statusBg = app.status === 'approved' ? '#dcfce7' : (app.status === 'rejected' ? '#fee2e2' : '#fef3c7'); 5064 const assignedCode = app.partnerCode || app.id; 5065 const encodedWaMsg = encodeURIComponent(`Hello ${app.name},\n\nYour B2B Partner Portal ID with Kavya Global Network has been activated:\n\nð Partner ID: ${assignedCode}\nð¢ Agency: ${app.company || 'Partner'}\nð Dispatch Portal: https://kavyaglobalnetwork.com.np/b2b\n\nYou can now use this Partner ID to unlock and dispatch student application files, transcripts, and financial documents directly to our central admissions team.`); 5066 5067 return ` 5068 <tr> 5069 <td> 5070 <div style="display: flex; flex-direction: column; gap: 6px;"> 5071 <div style="display: flex; align-items: center; gap: 6px; flex-wrap: wrap;"> 5072 <code style="background: #0f172a; color: #38bdf8; padding: 4px 8px; border-radius: 5px; font-size: 11.5px; font-family: 'Courier New', monospace; font-weight: 800; letter-spacing: 0.5px;"> 5073 ${assignedCode} 5074 </code> 5075 <button class="btn-copy-code" data-code="${assignedCode}" style="background: #f1f5f9; border: 1px solid #cbd5e1; color: #475569; width: 24px; height: 24px; border-radius: 4px; cursor: pointer; display: flex; align-items: center; justify-content: center;" title="Copy Partner ID"> 5076 <i class="fa-regular fa-copy" style="font-size: 11px;"></i> 5077 </button> 5078 </div> 5079 <div style="display: flex; gap: 5px; align-items: center;"> 5080 <span style="background: ${isSubAgent ? '#e0e7ff' : '#dbeafe'}; color: ${isSubAgent ? '#3730a3' : '#1e40af'}; padding: 2px 7px; border-radius: 4px; font-size: 10.5px; font-weight: 700;"> 5081 <i class="fa-solid ${isSubAgent ? 'fa-handshake' : 'fa-building-columns'}"></i> ${isSubAgent ? 'Sub-Agent' : 'University'} 5082 </span> 5083 <span style="background: ${statusBg}; color: ${statusColor}; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 800; text-transform: uppercase;"> 5084 ${app.status} 5085 </span> 5086 </div> 5087 </div> 5088 </td> 5089 <td> 5090 <div style="font-weight: 800; color: #00332a; font-size: 14px;">${app.name}</div> 5091 <div style="font-size: 12px; color: #555; margin-top: 3px;"> 5092 <a href="mailto:${app.email}" style="color: #006051; text-decoration: none;"><i class="fa-regular fa-envelope"></i> ${app.email}</a> 5093 </div> 5094 <div style="font-size: 12px; color: #555; margin-top: 2px;"> 5095 <a href="https://wa.me/${cleanPhone}?text=${encodedWaMsg}" target="_blank" style="color: #25d366; text-decoration: none; font-weight: 700;"> 5096 <i class="fa-brands fa-whatsapp"></i> ${app.phone} 5097 </a> 5098 </div> 5099 </td> 5100 <td> 5101 <div style="font-weight: 700; color: #333;">
5101${app.company || 'N/A'}</div> 5102 ${app.location ? `<div style="font-size: 12px; color: #666; margin-top: 2px;"><i class="fa-solid fa-location-dot"></i> ${app.location}</div>` : ''} 5103 ${app.website ? `<div style="font-size: 11.5px; margin-top: 3px;"><a href="${app.website}" target="_blank" style="color: #004a3e; text-decoration: underline;"><i class="fa-solid fa-globe"></i> Website</a></div>` : ''} 5104 ${app.license ? `<div style="font-size: 11px; color: #888; margin-top: 2px;">License: ${app.license}</div>` : ''} 5105 </td> 5106 <td> 5107 ${app.studentVolume ? `<div style="font-size: 12px; font-weight: 600; color: #004a3e;"><i class="fa-solid fa-users"></i> ${app.studentVolume}</div>` : ''} 5108 ${app.commission ? `<div style="font-size: 12px; color: #444;"><i class="fa-solid fa-handshake"></i> ${app.commission}</div>` : ''} 5109 ${app.countries && app.countries.length ? `<div style="font-size: 11px; color: #666; margin-top: 4px;">Countries: ${Array.isArray(app.countries) ? app.countries.join(', ') : app.countries}</div>` : ''} 5110 ${app.programs ? `<div style="font-size: 11px; color: #666; margin-top: 2px;">Programs: ${app.programs}</div>` : ''} 5111 ${app.message ? `<div style="font-size: 11.5px; color: #666; font-style: italic; margin-top: 4px; max-width: 240px; white-space: pre-wrap;">"${app.message}"</div>` : ''} 5112 </td> 5113 <td style="font-size: 12px; color: #666;"> 5114 ${new Date(app.appliedAt).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })} 5115 </td> 5116 <td> 5117 <div style="display: flex; flex-direction: column; gap: 6px;"> 5118 <div style="display: flex; gap: 4px; justify-content: center;"> 5119 <button class="btn-edit-partner" data-id="${app.id}" style="background: #e0f2fe; color: #0369a1; border: 1px solid #bae6fd; padding: 4px 8px; border-radius: 5px; cursor: pointer; font-size: 11px; font-weight: 700; display: flex; align-items: center; gap: 4px;" title="Edit Partner & Re-assign ID"> 5120 <i class="fa-solid fa-pen-to-square"></i> Edit ID 5121 </button> 5122 <a href="https://wa.me/${cleanPhone}?text=${encodedWaMsg}" target="_blank" style="background: #dcfce7; color: #15803d; border: 1px solid #bbf7d0; padding: 4px 8px; border-radius: 5px; text-decoration: none; font-size: 11px; font-weight: 700; display: inline-flex; align-items: center; gap: 4px;" title="Send ID Credentials via WhatsApp"> 5123 <i class="fa-brands fa-whatsapp"></i> Send ID 5124 </a> 5125 </div> 5126 <div style="display: flex; gap: 4px; justify-content: center;"> 5127 ${app.status !== 'approved' ? ` 5128 <button class="btn-approve-partner" data-id="${app.id}" style="background: #f0fdf4; color: #16a34a; border: 1px solid #bbf7d0; padding: 3px 8px; border-radius: 4px; cursor: pointer; font-size: 10.5px; font-weight: 700;
5128" title="Approve Partner"> 5129 <i class="fa-solid fa-check"></i> Approve 5130 </button> 5131 ` : ''} 5132 ${app.status !== 'rejected' ? ` 5133 <button class="btn-reject-partner" data-id="${app.id}" style="background: #fef2f2; color: #dc2626; border: 1px solid #fecaca; padding: 3px 8px; border-radius: 4px; cursor: pointer; font-size: 10.5px; font-weight: 700;" title="Decline Partner"> 5134 <i class="fa-solid fa-xmark"></i> Decline 5135 </button> 5136 ` : ''} 5137 <button class="btn-delete-partner" data-id="${app.id}" style="background: rgba(220, 53, 69, 0.08); color: #dc3545; border: 1px solid rgba(220, 53, 69, 0.2); padding: 3px 8px; border-radius: 4px; cursor: pointer; font-size: 10.5px;" title="Delete Partner Record"> 5138 <i class="fa-solid fa-trash-can"></i> 5139 </button> 5140 </div> 5141 </div> 5142 </td> 5143 </tr> 5144 `; 5145 }).join('')} 5146 </tbody> 5147 </table> 5148 </div> 5149 `} 5150 </div> 5151 `; 5152 5153 default: 5154 return `<p>Select a tab from the sidebar to edit website content.</p>`; 5155 } 5156 } 5157 5158 function bindEvents() { 5159 // Initialize B2B Direct File Dispatcher & Review Container if present 5160 if (window.initB2bDropzone) window.initB2bDropzone(); 5161 if (window.renderB2bReviewList) window.renderB2bReviewList(); 5162 5163 // Universal Counseling triggers across pages 5164 document.querySelectorAll('.btn-trigger-counseling').forEach(btn => { 5165 btn.onclick = () => { 5166 isCounselingOpen = true; 5167 counselingStatus = null; 5168 renderApp(); 5169 }; 5170 }); 5171 5172 // Client-side SPA Router navigation 5173 document.querySelectorAll('a[data-route]').forEach(link => { 5174 link.onclick = (e) => { 5175 const route = link.getAttribute('data-route'); 5176 if (!route) return; 5177 e.preventDefault(); 5178 isMobileMenuOpen = false; 5179 5180 const hashIdx = route.indexOf('#'); 5181 5182 if (route.startsWith('/#')) { 5183 // Home page hash anchor e.g. /#section-id 5184 const targetId = route.substring(2); 5185 if (window.location.pathname !== '/' && window.location.pathname !== '') { 5186 history.pushState({}, '', '/' + route.substring(1)); 5187 renderApp(); 5188 setTimeout(() => { 5189 const el = document.getElementById(targetId); 5190 if (el) el.scrollIntoView({ behavior: 'smooth' }); 5191 }, 120); 5192 } else { 5193 history.pushState({}, '', route.substring(1)); 5194 const el = document.getElementById(targetId); 5195 if (el) el.scrollIntoView({ behavior: 'smooth' }); 5196 } 5197 } else if (hashIdx > 0) { 5198 // Cross-page anchor e.g. /b2b#b2b-file-transfer 5199 const pagePath = route.substring(0, hashIdx); 5200 const targetId = route.substring(hashIdx + 1); 5201 if (window.location.pathname !== pagePath) { 5202 history.pushState({}, '', route); 5203 renderApp(); 5204 setTimeout(() => { 5205 const el = document.getElementById(targetId); 5206 if (el) el.scrollIntoView({ behavior: 'smooth' }); 5207 }, 150); 5208 } else { 5209 history.pushState({}, '', route); 5210 const el = document.getElementById(targetId); 5211 if (el) el.scrollIntoView({ behavior: 'smooth' }); 5212 } 5213 } else { 5214 // Normal page route 5215 history.pushState({}, '', route); 5216 renderApp(); 5217 window.scrollTo({ top: 0, behavior: 'smooth' }); 5218 } 5219 }; 5220 }); 5221 5222 // Mobile Navigation Drawer Toggle & Close 5223 const toggleMobileMenu = () => { 5224 isMobileMenuOpen = !isMobileMenuOpen; 5225 renderApp(); 5226 }; 5227 5228 const btnToggleMobileMenu = document.getElementById('btn-mobile-menu-toggle'); 5229 if (btnToggleMobileMenu) { 5230 btnToggleMobileMenu.onclick = toggleMobileMenu; 5231 } 5232 5233 const mobBottomMenuToggle = document.getElementById('mob-bottom-menu
5233-toggle'); 5234 if (mobBottomMenuToggle) { 5235 mobBottomMenuToggle.onclick = toggleMobileMenu; 5236 } 5237 5238 const btnCloseMobileMenu = document.getElementById('btn-close-mobile-drawer'); 5239 if (btnCloseMobileMenu) { 5240 btnCloseMobileMenu.onclick = () => { 5241 isMobileMenuOpen = false; 5242 renderApp(); 5243 }; 5244 } 5245 5246 const backdropMobile = document.getElementById('mobile-drawer-backdrop'); 5247 if (backdropMobile) { 5248 backdropMobile.onclick = (e) => { 5249 if (e.target === backdropMobile) { 5250 isMobileMenuOpen = false; 5251 renderApp(); 5252 } 5253 }; 5254 } 5255 5256 // Admin CMS Modal Trigger 5257 const btnOpenAdmin = document.getElementById('btn-open-admin'); 5258 if (btnOpenAdmin) { 5259 btnOpenAdmin.onclick = () => { 5260 isAdminOpen = true; 5261 history.pushState({}, '', '/admin'); 5262 renderApp(); 5263 }; 5264 } 5265 5266 // Quick Layout Toggle Button 5267 const btnToggleLayout = document.getElementById('btn-toggle-layout'); 5268 if (btnToggleLayout) { 5269 btnToggleLayout.onclick = () => { 5270 const current = siteData.general.layoutMode || 'full-width'; 5271 siteData.general.layoutMode = current === 'full-width' ? 'boxed' : 'full-width'; 5272 saveSiteData(siteData); 5273 }; 5274 } 5275 5276 // Counseling Modal Triggers 5277 const btnOpenCounsel = document.getElementById('btn-open-counseling'); 5278 if (btnOpenCounsel) { 5279 btnOpenCounsel.onclick = () => { 5280 isCounselingOpen = true; 5281 counselingStatus = null; 5282 isMobileMenuOpen = false; 5283 renderApp(); 5284 }; 5285 } 5286 5287 const btnOpenCounselVisa = document.getElementById('btn-open-counseling-visa'); 5288 if (btnOpenCounselVisa) { 5289 btnOpenCounselVisa.onclick = () => { 5290 isCounselingOpen = true; 5291 counselingStatus = null; 5292 isMobileMenuOpen = false; 5293 renderApp(); 5294 }; 5295 } 5296 5297 const btnCloseCounsel = document.getElementById('btn-close-counseling-modal'); 5298 if (btnCloseCounsel) { 5299 btnCloseCounsel.onclick = () => { 5300 isCounselingOpen = false; 5301 counselingStatus = null; 5302 renderApp(); 5303 }; 5304 } 5305 5306 const backdropCounsel = document.getElementById('counseling-backdrop'); 5307 if (backdropCounsel) { 5308 backdropCounsel.onclick = (e) => { 5309 if (e.target === backdropCounsel) { 5310 isCounselingOpen = false; 5311 counselingStatus = null; 5312 renderApp(); 5313 } 5314 }; 5315 } 5316 5317 // Mock Test Modal Triggers 5318 document.querySelectorAll('.btn-trigger-mock-test').forEach(btn => { 5319 btn.onclick = (e) => { 5320 e.preventDefault(); 5321 isMockModalOpen = true; 5322 formStatus = null; 5323 if (isMobileMenuOpen) isMobileMenuOpen = false; 5324 renderApp(); 5325 }; 5326 }); 5327 5328 const btnCloseMock = document.getElementById('btn-close-mock-modal'); 5329 if (btnCloseMock) { 5330 btnCloseMock.onclick = () => { 5331 isMockModalOpen = false; 5332 formStatus = null; 5333 renderApp(); 5334 }; 5335 } 5336 5337 const backdropMock = document.getElementById('mock-modal-backdrop'); 5338 if (backdropMock) { 5339 backdropMock.onclick = (e) => { 5340 if (e.target === backdropMock) { 5341 isMockModalOpen = false; 5342 formStatus = null; 5343 renderApp(); 5344 } 5345 }; 5346 } 5347 5348 const mockModalForm = document.getElementById('mock-modal-form'); 5349 if (mockModalForm) { 5350 const mName = document.getElementById('mock-m-name'); 5351 if (mName) mName.oninput = (e) => formState.name = e.target.value; 5352 const mPhone = document.getElementById('mock-m-phone'); 5353 if (mPhone) mPhone.oninput = (e) => formState.phone = e.target.value; 5354 const mEmail = document.getElementById('mock-m-email'); 5355 if (mEmail) mEmail.oninput = (e) => formState.email = e.target.value; 5356 const mAddr = document.getElementById('mock-m-address'); 5357 if (mAddr) mAddr.onchange = (e) => formState.address = e.target.value; 5358 const mType = document.getElementById('mock-m-testtype'); 5359 if (mType) mType.onchange = (e) => formState.testType = e.target.value; 5360 const mSlot = document.getElementById('mock-m-timeslot'); 5361 if (mSlot) mSlot.onchange = (e) => formState.timeSlot = e.target.value; 5362 const mDate = document.getElementById('mock-m-date'); 5363 if (mDate) mDate.oninput = (e) => formState.date = e.target.value; 5364 5365 mockModalForm.onsubmit = async (e) => { 5366 e.preventDefault(); 5367 if (mName) formState.name = mName.value; 5368 if (mPhone) formState.phone = mPhone.value; 5369 if (mEmail) formState.email = mEmail.value; 5370 if (mAddr) formState.address = mAddr.value; 5371 if (mType) formState.testType = mType.value; 5372 if (mSlot) formState.timeSlot = mSlot.value; 5373 if (mDate) formState.date = mDate.value; 5374 5375 const submitBtn = mockModalForm.querySelector('button[type="submit"]'); 5376 if (submitBtn) { 5377 submitBtn.disabled = true; 5378 submitBtn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Submitting...'; 5379 } 5380 await submitForm(e); 5381 }; 5382 } 5383 5384 // Keyboard Accessibility (ESC key to close open dialogs) 5385 window.onkeydown = (e) => { 5386 if (e.key === 'Escape') { 5387 if (window.closePartnerModal) { 5388 window.closePartnerModal(); 5389 } 5390 if (isMockModalOpen) { 5391 isMockModalOpen = false;
5392 formStatus = null; 5393 renderApp(); 5394 } else if (isCounselingOpen) { 5395 isCounselingOpen = false; 5396 counselingStatus = null; 5397 renderApp(); 5398 } else if (isMobileMenuOpen) { 5399 isMobileMenuOpen = false; 5400 renderApp(); 5401 } 5402 } 5403 }; 5404 5405 const counselForm = document.getElementById('counseling-modal-form'); 5406 if (counselForm) { 5407 const cName = document.getElementById('counsel-name'); 5408 if (cName) cName.oninput = (e) => counselingState.name = e.target.value; 5409 const cEmail = document.getElementById('counsel-email'); 5410 if (cEmail) cEmail.oninput = (e) => counselingState.email = e.target.value; 5411 const cPhone = document.getElementById('counsel-phone'); 5412 if (cPhone) cPhone.oninput = (e) => counselingState.phone = e.target.value; 5413 const cCountry = document.getElementById('counsel-country'); 5414 if (cCountry) cCountry.onchange = (e) => counselingState.country = e.target.value; 5415 const cDate = document.getElementById('counsel-date'); 5416 if (cDate) cDate.oninput = (e) => counselingState.preferredDate = e.target.value; 5417 const cMsg = document.getElementById('counsel-msg'); 5418 if (cMsg) cMsg.oninput = (e) => counselingState.message = e.target.value; 5419 counselForm.onsubmit = submitCounselingForm; 5420 } 5421 5422 // Session type switcher buttons inside counseling modal 5423 document.querySelectorAll('.counseling-type-btn').forEach(btn => { 5424 btn.onclick = () => { 5425 counselingState.sessionType = btn.dataset.session; 5426 counselingStatus = null; 5427 renderApp(); 5428 }; 5429 }); 5430 5431 // Admin Login Form Handler 5432 const adminLoginForm = document.getElementById('admin-login-form'); 5433 if (adminLoginForm) { 5434 adminLoginForm.onsubmit = (e) => { 5435 e.preventDefault(); 5436 const passInput = document.getElementById('admin-pass-input'); 5437 if (passInput) loginAdmin(passInput.value); 5438 }; 5439 } 5440 5441 const btnCancelAdminLogin = document.getElementById('btn-cancel-admin-login'); 5442 if (btnCancelAdminLogin) { 5443 btnCancelAdminLogin.onclick = () => { 5444 isAdminOpen = false; 5445 loginErrorMsg = ''; 5446 if (window.location.hash === '#admin') { 5447 history.pushState('', document.title, window.location.pathname + window.location.search); 5448 } 5449 renderApp(); 5450 }; 5451 } 5452 5453 const btnAdminLogout = document.getElementById('btn-admin-logout'); 5454 if (btnAdminLogout) {
5455 btnAdminLogout.onclick = () => { 5456 sessionStorage.removeItem('kgn_admin_authenticated'); 5457 isAdminOpen = false; 5458 history.pushState({}, '', '/'); 5459 renderApp(); 5460 }; 5461 } 5462 5463 const btnSaveNewPass = document.getElementById('btn-save-new-pass'); 5464 if (btnSaveNewPass) { 5465 btnSaveNewPass.onclick = () => { 5466 const currPass = document.getElementById('admin-curr-pass').value; 5467 const newPass = document.getElementById('admin-new-pass').value; 5468 changeAdminPassword(currPass, newPass); 5469 }; 5470 } 5471 5472 const btnViewLiveSite = document.getElementById('btn-view-live-site'); 5473 if (btnViewLiveSite) { 5474 btnViewLiveSite.onclick = () => { 5475 isAdminOpen = false; 5476 history.pushState({}, '', '/'); 5477 renderApp(); 5478 }; 5479 } 5480 5481 const btnViewLiveSiteLogin = document.getElementById('btn-view-live-site-login'); 5482 if (btnViewLiveSiteLogin) { 5483 btnViewLiveSiteLogin.onclick = () => { 5484 isAdminOpen = false; 5485 history.pushState({}, '', '/'); 5486 renderApp(); 5487 }; 5488 } 5489 5490 document.querySelectorAll('.admin-sidebar-item, .admin-nav-btn').forEach(btn => { 5491 btn.onclick = () => { 5492 activeAdminTab = btn.dataset.tab; 5493 renderApp(); 5494 }; 5495 }); 5496 5497 document.querySelectorAll('.lead-filter-tab').forEach(tab => { 5498 tab.onclick = () => { 5499 activeLeadFilter = tab.dataset.filter; 5500 renderApp(); 5501 }; 5502 }); 5503 5504 document.querySelectorAll('.btn-delete-lead').forEach(btn => { 5505 btn.onclick = (e) => { 5506 const id = e.currentTarget.dataset.id; 5507 if (id) deleteLead(id); 5508 }; 5509 }); 5510 5511 document.querySelectorAll('.btn-approve-partner').forEach(btn => { 5512 btn.onclick = (e) => { 5513 const id = e.currentTarget.dataset.id; 5514 if (id) updatePartnerAppStatus(id, 'approved'); 5515 }; 5516 }); 5517 5518 document.querySelectorAll('.btn-reject-partner').forEach(btn => { 5519 btn.onclick = (e) => { 5520 const id = e.currentTarget.dataset.id; 5521 if (id) updatePartnerAppStatus(id, 'rejected'); 5522 }; 5523 }); 5524 5525 document.querySelectorAll('.btn-delete-partner').forEach(btn => { 5526 btn.onclick = (e) => { 5527 const id = e.currentTarget.dataset.id; 5528 if (id) deletePartnerApp(id); 5529 }; 5530 }); 5531 5532 // Partner search and filtering handlers 5533 const partnerSearchInput = document.getElementById('partner-search-input'); 5534 if (partnerSearchInput) { 5535 partnerSearchInput.oninput = (e) => { 5536 partnerSearchQuery = e.target.value; 5537 renderApp(); 5538 const reInput = document.getElementById('partner-search-input'); 5539 if (reInput) { 5540 reInput.focus(); 5541 reInput.setSelectionRange(reInput.value.length, reInput.value.length); 5542 } 5543 }; 5544 } 5545 5546 const partnerTypeFilterEl = document.getElementById('partner-type-filter'); 5547 if (partnerTypeFilterEl) { 5548 partnerTypeFilterEl.onchange = (e) => { 5549 partnerTypeFilter = e.target.value; 5550 renderApp(); 5551 }; 5552 } 5553 5554 const partnerStatusFilterEl = document.getElementById('partner-status-filter'); 5555 if (partnerStatusFilterEl) { 5556 partnerStatusFilterEl.onchange = (e) => { 5557 partnerStatusFilter = e.target.value; 5558 renderApp(); 5559 }; 5560 } 5561 5562 const btnClearFilters = document.getElementById('btn-clear-partner-filters'); 5563 if (btnClearFilters) { 5564 btnClearFilters.onclick = () => { 5565 partnerSearchQuery = ''; 5566 partnerTypeFilter = 'all'; 5567 partnerStatusFilter = 'all'; 5568 renderApp(); 5569 }; 5570 } 5571 5572 // Add Partner Modal Triggers 5573 const btnAddPartner = document.getElementById('btn-admin-add-partner'); 5574 if (btnAddPartner) btnAddPartner.onclick = () => window.openAdminAddPartnerModal(); 5575 const btnAddPartnerEmpty = document.getElementById('btn-admin-add-partner-empty'); 5576 if (btnAddPartnerEmpty) btnAddPartnerEmpty.onclick = () => window.openAdminAddPartnerModal(); 5577 5578 // Edit Partner Modal Triggers 5579 document.querySelectorAll('.btn-edit-partner').forEach(btn => { 5580 btn.onclick = (e) => { 5581 const id = e.currentTarget.dataset.id; 5582 if (id) window.openAdminEditPartnerModal(id); 5583 }; 5584 }); 5585 5586 // Copy Partner Code to Clipboard 5587 document.querySelectorAll('.btn-copy-code').forEach(btn => { 5588 btn.onclick = (e) => { 5589 const code = e.currentTarget.dataset.code; 5590 if (code) copyToClipboard(code, `Partner ID "${code}" copied to clipboard!`); 5591 }; 5592 }); 5593 5594 const bookingForm = document.getElementById('mock-booking-form'); 5595 if (bookingForm) { 5596 const fName = document.getElementById('field-name'); 5597 if (fName) fName.oninput = (e) => formState.name = e.target.value; 5598 const fEmail = document.getElementById('field-email'); 5599 if (fEmail) fEmail.oninput = (e) => formState.email = e.target.value; 5600 const fPhone = document.getElementById('field-phone'); 5601 if (fPhone) fPhone.oninput = (e) => formState.phone = e.target.value; 5602 const ttype = document.getElementById('field-testtype'); 5603 if (ttype) ttype.onchange = (e) => formState.testType = e.target.value; 5604 const tslot = document.getElementById('field-timeslot'); 5605 if (tslot) tslot.onchange = (e) => formState.timeSlot = e.target.value; 5606 bookingForm.onsubmit = (e) => { 5607 if (fName) formState.name = fName.value; 5608 if (fEmail) formState.email = fEmail.value; 5609 if (fPhone) formState.phone = fPhone.value; 5610 submitForm(e); 5611 }; 5612 } 5613 5614 // Admin Section Savers â Covers Every Single Section on the Website 5615 5616 // 1. Top Bar & Contacts 5617 const btnSaveTopbar = document.getElementById('btn-save-topbar'); 5618 if (btnSaveTopbar) { 5619 btnSaveTopbar.onclick = () => { 5620 if (!siteData.topBar) siteData.topBar = {}; 5621 siteData.topBar.phone = document.getElementById('admin-topbar-phone').value; 5622 siteData.topBar.mobile = document.getElementById('admin-topbar-mobile').value; 5623 siteData.topBar.email = document.getElementById('admin-topbar-email').value; 5624 siteData.topBar.address = document.getElementById('admin-topbar-address').value; 5625 siteData.topBar.announcement = document.getElementById('admin-topbar-announcement').value; 5626 // Keep general synced as well 5627 if (siteData.general) {
5628 siteData.general.phone = siteData.topBar.phone; 5629 siteData.general.mobilePhone = siteData.topBar.mobile; 5630 siteData.general.email = siteData.topBar.email; 5631 siteData.general.address = siteData.topBar.address; 5632 } 5633 saveSiteData(siteData); 5634 }; 5635 } 5636 5637 // 2. Header & Branding 5638 const btnSaveHeader = document.getElementById('btn-save-header'); 5639 if (btnSaveHeader) { 5640 btnSaveHeader.onclick = () => { 5641 if (!siteData.header) siteData.header = {}; 5642 const logoEl = document.getElementById('admin-header-logo'); 5643 if (logoEl) siteData.header.logoUrl = logoEl.value; 5644 const btnEl = document.getElementById('admin-header-btn'); 5645 if (btnEl) siteData.header.counselingBtnText = btnEl.value; 5646 saveSiteData(siteData); 5647 }; 5648 } 5649 5650 // 3. Hero Section 5651 const btnSaveHero = document.getElementById('btn-save-hero'); 5652 if (btnSaveHero) { 5653 btnSaveHero.onclick = () => { 5654 if (!siteData.hero) siteData.hero = {}; 5655 const bgEl = document.getElementById('admin-hero-badge'); 5656 if (bgEl) siteData.hero.badge = bgEl.value; 5657 siteData.hero.eyebrow = document.getElementById('admin-hero-eyebrow').value; 5658 siteData.hero.titlePart1 = document.getElementById('admin-hero-title1').value; 5659 siteData.hero.titleUSA = document.getElementById('admin-hero-usa').value; 5660 const andEl = document.getElementById('admin-hero-and'); 5661 if (andEl) siteData.hero.titleAnd = andEl.value; 5662 siteData.hero.titleAustralia = document.getElementById('admin-hero-aus').value; 5663 siteData.hero.description = document.getElementById('admin-hero-desc').value; 5664 const trEl = document.getElementById('admin-hero-trust'); 5665 if (trEl) siteData.hero.trustText = trEl.value; 5666 siteData.hero.heroImage = document.getElementById('admin-hero-img').value; 5667 const pteTag = document.getElementById('admin-hero-pte-tag'); 5668 if (pteTag) siteData.hero.badgePte = pteTag.value; 5669 siteData.hero.badgePteTitle = document.getElementById('admin-hero-pte-title').value; 5670 const pteSub = document.getElementById('admin-hero-pte-sub'); 5671 if (pteSub) siteData.hero.badgePteSub = pteSub.value; 5672 saveSiteData(siteData); 5673 }; 5674 } 5675 5676 // 4. Stats Counters 5677 const btnAddCounter = document.getElementById('btn-add-counter'); 5678 if (btnAddCounter) { 5679 btnAddCounter.onclick = () => { 5680 if (!siteData.counters) siteData.counters = []; 5681 siteData.counters.push({ 5682 id: 'c_' + Date.now(), 5683 icon: 'fa-award', 5684 number: '99%', 5685 label: 'NEW COUNTER' 5686 }); 5687 saveSiteData(siteData); 5688 }; 5689 } 5690 5691 document.querySelectorAll('.btn-delete-counter').forEach(btn => { 5692 btn.onclick = (e) => { 5693 const idx = parseInt(e.currentTarget.dataset.index, 10); 5694 if (!isNaN(idx) && siteData.counters) { 5695 siteData.counters.splice(idx, 1); 5696 saveSiteData(siteData); 5697 } 5698 }; 5699 }); 5700 5701 const btnSaveCounters = document.getElementById('btn-save-counters'); 5702 if (btnSaveCounters) { 5703 btnSaveCounters.onclick = () => { 5704 siteData.counters.forEach((c, i) => { 5705 const n = document.getElementById(`admin-counter-num-${i}`); 5706 if (n) c.number = n.value; 5707 const l = document.getElementById(`admin-counter-label-${i}`); 5708 if (l) c.label = l.value; 5709 }); 5710 saveSiteData(siteData); 5711 }; 5712 } 5713 5714 // 4b. About Page Content 5715 const btnSaveAbout = document.getElementById('btn-save-about'); 5716 if (btnSaveAbout) { 5717 btnSaveAbout.onclick = () => { 5718 if (!siteData.about) siteData.about = {}; 5719 siteData.about.title = document.getElementById('admin-about-title').value; 5720 siteData.about.subtitle = document.getElementById('admin-about-sub').value; 5721 siteData.about.storyBadge = document.getElementById('admin-about-badge').value; 5722 siteData.about.storyTitle = document.getElementById('admin-about-story-title').value; 5723 siteData.about.storyP1 = document.getElementById('admin-about-p1').value; 5724 siteData.about.storyP2 = document.getElementById('admin-about-p2').value; 5725 siteData.about.storyImage = document.getElementById('admin-about-img').value; 5726 siteData.about.vision = document.getElementById('admin-about-vision').value; 5727 siteData.about.mission = document.getElementById('admin-about-mission').value; 5728 saveSiteData(siteData); 5729 }; 5730 } 5731 5732 // 5. Director Leadership Message 5733 const btnSaveDir = document.getElementById('btn-save-director'); 5734 if (btnSaveDir) { 5735 btnSaveDir.onclick = () => { 5736 if (!siteData.directorMessage) siteData.directorMessage = {}; 5737 siteData.directorMessage.tag = document.getElementById('admin-dir-tag').value; 5738 siteData.directorMessage.title = document.getElementById('admin-dir-title').value; 5739 siteData.directorMessage.name = document.getElementById('admin-dir-name').value; 5740 siteData.directorMessage.role = document.getElementById('admin-dir-role').value; 5741 const badgeEl = document.getElementById('admin-dir-badge'); 5742 if (badgeEl) siteData.directorMessage.badge = badgeEl.value; 5743 siteData.directorMessage.quote = document.getElementById('admin-dir-quote').value; 5744 siteData.directorMessage.description = document.getElementById('admin-dir-desc').value; 5745 siteData.directorMessage.image = document.getElementById('admin-dir-image').value; 5746 saveSiteData(siteData); 5747 }; 5748 } 5749 5750 // 6. Global University Partners 5751 const btnAddPartnerUni = document.getElementById('btn-add-partner-uni'); 5752 if (btnAddPartnerUni) { 5753 btnAddPartnerUni.onclick = () => { 5754 if (!siteData.partners) siteData.partners = { title: 'OUR TRUSTED GLOBAL UNIVERSITY PARTNERS', logos: [] }; 5755 siteData.partners.logos.push({ 5756 name: 'New University Partner', 5757 location: 'Global', 5758 logo: 'ðï¸ New University', 5759 img: '' 5760 }); 5761 saveSiteData(siteData); 5762 }; 5763 } 5764 5765 document.querySelectorAll('.btn-delete-partner-uni').forEach(btn => { 5766 btn.onclick = (e) => { 5767 const idx = parseInt(e.currentTarget.dataset.index, 10); 5768 if (!isNaN(idx) && siteData.partners && siteData.partners.logos) { 5769 siteData.partners.logos.splice(idx, 1); 5770 saveSiteData(siteData); 5771 } 5772 }; 5773 }); 5774 5775 const btnSavePartners = document.getElementById('btn-save-partners'); 5776 if (btnSavePartners) { 5777 btnSavePartners.onclick = () => { 5778 if (!siteData.partners) siteData.partners = { logos: [] }; 5779 siteData.partners.title = document.getElementById('admin-
5779partners-title').value; 5780 siteData.partners.logos.forEach((p, i) => { 5781 const nEl = document.getElementById(`admin-partner-name-${i}`); 5782 if (nEl) p.name = nEl.value; 5783 const lEl = document.getElementById(`admin-partner-loc-${i}`); 5784 if (lEl) p.location = lEl.value; 5785 const lgEl = document.getElementById(`admin-partner-logo-${i}`); 5786 if (lgEl) p.logo = lgEl.value; 5787 const imgEl = document.getElementById(`admin-partner-img-${i}`); 5788 if (imgEl) p.img = imgEl.value; 5789 }); 5790 saveSiteData(siteData); 5791 }; 5792 } 5793 5794 // 7. Services Section 5795 const btnAddService = document.getElementById('btn-add-service'); 5796 if (btnAddService) { 5797 btnAddService.onclick = () => { 5798 if (!siteData.services) siteData.services = { items: [] }; 5799 siteData.services.items.push({ 5800 id: 'serv_' + Date.now(), 5801 title: 'New Student Service', 5802 description: 'Personalized assistance and guidance tailored to each student.' 5803 }); 5804 saveSiteData(siteData); 5805 }; 5806 } 5807 5808 document.querySelectorAll('.btn-delete-service').forEach(btn => { 5809 btn.onclick = (e) => { 5810 const idx = parseInt(e.currentTarget.dataset.index, 10); 5811 if (!isNaN(idx) && siteData.services && siteData.services.items) { 5812 siteData.services.items.splice(idx, 1); 5813 saveSiteData(siteData); 5814 } 5815 }; 5816 }); 5817 5818 const btnSaveServices = document.getElementById('btn-save-services'); 5819 if (btnSaveServices) { 5820 btnSaveServices.onclick = () => { 5821 siteData.services.tag = document.getElementById('admin-serv-tag').value; 5822 siteData.services.title = document.getElementById('admin-serv-title').value; 5823 siteData.services.description = document.getElementById('admin-serv-desc').value; 5824 siteData.services.items.forEach((s, i) => { 5825 const t = document.getElementById(`admin-serv-item-title-${i}`); 5826 if (t) s.title = t.value; 5827 const d = document.getElementById(`admin-serv-item-desc-${i}`); 5828 if (d) s.description = d.value; 5829 }); 5830 saveSiteData(siteData); 5831 }; 5832 } 5833 5834 // 8. Destinations Section (Includes Germany) 5835 const btnAddDest = document.getElementById('btn-add-destination'); 5836 if (btnAddDest) { 5837 btnAddDest.onclick = () => { 5838 if (!siteData.destinations) siteData.destinations = { items: [] }; 5839 siteData.destinations.items.push({ 5840 id: 'dest_' + Date.now(), 5841 title: 'Study in Germany', 5842 badge: '', 5843 subBadge: '', 5844 image: 'https://images.unsplash.com/photo-1467269204594-9661b134dd2b?q=80&w=800&auto=format&fit=crop' 5845 }); 5846 saveSiteData(siteData); 5847 }; 5848 } 5849 5850 document.querySelectorAll('.btn-delete-destination').forEach(btn => { 5851 btn.onclick = (e) => { 5852 const idx = parseInt(e.currentTarget.dataset.index, 10); 5853 if (!isNaN(idx) && siteData.destinations && siteData.destinations.items) { 5854 siteData.destinations.items.splice(idx, 1); 5855 saveSiteData(siteData); 5856 } 5857 }; 5858 }); 5859 5860 const btnSaveDestinations = document.getElementById('btn-save-destinations'); 5861 if (btnSaveDestinations) { 5862 btnSaveDestinations.onclick = () => { 5863 siteData.destinations.tag = document.getElementById('admin-dest-tag').value; 5864 siteData.destinations.title = document.getElementById('admin-dest-title').value; 5865 siteData.destinations.items.forEach((d, i) => { 5866 const t = document.getElementById(`admin-dest-item-title-${i}`); 5867 if (t) d.title = t.value; 5868 const img = document.getElementById(`admin-dest-item-img-${i}`); 5869 if (img) d.image = img.value; 5870 const b = document.getElementById(`admin-dest-item-badge-${i}`); 5871 if (b) d.badge = b.value; 5872 const sb = document.getElementById(`admin-dest-item-subbadge-${i}`); 5873 if (sb) d.subBadge = sb.value; 5874 }); 5875 saveSiteData(siteData); 5876 }; 5877 } 5878 5879 // 9. Visa Success Approvals Gallery 5880 const btnAddVisa = document.getElementById('btn-add-visa'); 5881 if (btnAddVisa) { 5882 btnAddVisa.onclick = () => { 5883 if (!siteData.visaSuccess) siteData.visaSuccess = { items: [] }; 5884 siteData.visaSuccess.items.push({ 5885 id: 'v_' + Date.now(), 5886 name: 'New Student', 5887 country: 'Germany', 5888 badge: 'VISA GRANTED', 5889 intake: '2026', 5890 university: 'Partner University',
5891 photo: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?q=80&w=600&auto=format&fit=crop' 5892 }); 5893 saveSiteData(siteData); 5894 }; 5895 } 5896 5897 document.querySelectorAll('.btn-delete-visa').forEach(btn => { 5898 btn.onclick = (e) => { 5899 const idx = parseInt(e.currentTarget.dataset.index, 10); 5900 if (!isNaN(idx) && siteData.visaSuccess && siteData.visaSuccess.items) { 5901 siteData.visaSuccess.items.splice(idx, 1); 5902 saveSiteData(siteData); 5903 } 5904 }; 5905 }); 5906 5907 const btnSaveVisa = document.getElementById('btn-save-visa'); 5908 if (btnSaveVisa) { 5909 btnSaveVisa.onclick = () => { 5910 if (!siteData.visaSuccess) siteData.visaSuccess = { items: [] }; 5911 siteData.visaSuccess.tag = document.getElementById('admin-visa-tag').value; 5912 siteData.visaSuccess.title = document.getElementById('admin-visa-title').value; 5913 siteData.visaSuccess.items.forEach((v, i) => { 5914 const n = document.getElementById(`admin-visa-name-${i}`); 5915 if (n) v.name = n.value; 5916 const c = document.getElementById(`admin-visa-country-${i}`); 5917 if (c) v.country = c.value; 5918 const b = document.getElementById(`admin-visa-badge-${i}`); 5919 if (b) v.badge = b.value; 5920 const u = document.getElementById(`admin-visa-uni-${i}`); 5921 if (u) v.university = u.value; 5922 const p = document.getElementById(`admin-visa-photo-${i}`); 5923 if (p) v.photo = p.value; 5924 }); 5925 saveSiteData(siteData); 5926 }; 5927 } 5928 5929 // 10. Test Prep & Mock Form 5930 const btnSaveTestPrep = document.getElementById('btn-save-testprep'); 5931 if (btnSaveTestPrep) { 5932 btnSaveTestPrep.onclick = () => { 5933 siteData.testPrep.tag = document.getElementById('admin-prep-tag').value; 5934 siteData.testPrep.title = document.getElementById('admin-prep-title').value; 5935 siteData.testPrep.description = document.getElementById('admin-prep-desc').value; 5936 siteData.testPrep.formTitle = document.getElementById('admin-prep-formtitle').value; 5937 siteData.testPrep.formSub = document.getElementById('admin-prep-formsub').value; 5938 saveSiteData(siteData); 5939 }; 5940 } 5941 5942 // 11. Accreditations & Badges 5943 const btnAddAccred = document.getElementById('btn-add-accred'); 5944 if (btnAddAccred) { 5945 btnAddAccred.onclick = () => { 5946 if (!siteData.accreditations) siteData.accreditations = { tag: 'RECOGNITION', title: 'Accreditations', description: '', items: [] }; 5947 siteData.accreditations.items.push({ 5948 id: 'cert_' + Date.now(), 5949 title: 'New Certificate', 5950 subtitle: 'Governing Body Name', 5951 icon: 'fa-award', 5952 badge: 'Certified' 5953 }); 5954 saveSiteData(siteData); 5955 }; 5956 } 5957 5958 document.querySelectorAll('.btn-delete-accred').forEach(btn => { 5959 btn.onclick = (e) => { 5960 const idx = parseInt(e.currentTarget.dataset.index, 10); 5961 if (!isNaN(idx) && siteData.accreditations && siteData.accreditations.items) { 5962 siteData.accreditations.items.splice(idx, 1); 5963 saveSiteData(siteData); 5964 } 5965 }; 5966 }); 5967 5968 const btnSaveAccred = document.getElementById('btn-save-accreditations'); 5969 if (btnSaveAccred) { 5970 btnSaveAccred.onclick = () => { 5971 if (!siteData.accreditations) siteData.accreditations = { items: [] }; 5972 siteData.accreditations.tag = document.getElementById('admin-accred-tag').value; 5973 siteData.accreditations.title = document.getElementById('admin-accred-title').value; 5974 siteData.accreditations.description = document.getElementById('admin-accred-desc').value; 5975 siteData.accreditations.items.forEach((a, i) => { 5976 const tEl = document.getElementById(`admin-accred-item-title-${i}`); 5977 if (tEl) a.title = tEl.value; 5978 const sEl = document.getElementById(`admin-accred-item-sub-${i}`); 5979 if (sEl) a.subtitle = sEl.value; 5980 const bEl = document.getElementById(`admin-accred-item-badge-${i}`); 5981 if (bEl) a.badge = bEl.value; 5982 }); 5983 saveSiteData(siteData); 5984 }; 5985 } 5986 5987 // 12. Student Google Reviews 5988 const btnAddTesti = document.getElementById('btn-add-testimonial'); 5989 if (btnAddTesti) { 5990 btnAddTesti.onclick = () => { 5991 if (!siteData.testimonials) siteData.testimonials = { reviews: [] }; 5992 siteData.testimonials.reviews.unshift({ 5993 id: 'g_' + Date.now(), 5994 name: 'New Student Reviewer', 5995 country: 'Germany ⢠International Student', 5996 rating: 5, 5997 date: 'Just now', 5998 review: 'Outstanding counseling experience with Kavya Global Network! Highly recommended for all students aspiring to study abroad.',
5999 avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?q=80&w=150&auto=format&fit=crop', 6000 badge: 'Verified Google Review' 6001 }); 6002 saveSiteData(siteData); 6003 }; 6004 } 6005 6006 document.querySelectorAll('.btn-delete-testimonial').forEach(btn => { 6007 btn.onclick = (e) => { 6008 const idx = parseInt(e.currentTarget.dataset.index, 10); 6009 if (!isNaN(idx) && siteData.testimonials && siteData.testimonials.reviews) { 6010 siteData.testimonials.reviews.splice(idx, 1); 6011 saveSiteData(siteData); 6012 } 6013 }; 6014 }); 6015 6016 const btnSaveTesti = document.getElementById('btn-save-testimonials'); 6017 if (btnSaveTesti) { 6018 btnSaveTesti.onclick = () => { 6019 if (!siteData.testimonials) siteData.testimonials = { reviews: [] }; 6020 siteData.testimonials.tag = document.getElementById('admin-testi-tag').value; 6021 siteData.testimonials.title = document.getElementById('admin-testi-title').value; 6022 siteData.testimonials.subtitle = document.getElementById('admin-testi-sub').value; 6023 siteData.testimonials.googleRating = document.getElementById('admin-testi-rating').value; 6024 siteData.testimonials.googleReviewCount = document.getElementById('admin-testi-count').value; 6025 siteData.testimonials.googleMapsUrl = document.getElementById('admin-testi-mapurl').value; 6026 6027 siteData.testimonials.reviews.forEach((r, i) => { 6028 const nEl = document.getElementById(`admin-testi-name-${i}`); 6029 if (nEl) r.name = nEl.value; 6030 const cEl = document.getElementById(`admin-testi-country-${i}`); 6031 if (cEl) r.country = cEl.value; 6032 const dEl = document.getElementById(`admin-testi-date-${i}`); 6033 if (dEl) r.date = dEl.value; 6034 const rwEl = document.getElementById(`admin-testi-review-${i}`); 6035 if (rwEl) r.review = rwEl.value; 6036 const aEl = document.getElementById(`admin-testi-avatar-${i}`); 6037 if (aEl) r.avatar = aEl.value; 6038 }); 6039 saveSiteData(siteData); 6040 }; 6041 } 6042 6043 // 13. FAQs Accordion 6044 const btnAddFaq = document.getElementById('btn-add-faq'); 6045 if (btnAddFaq) { 6046 btnAddFaq.onclick = () => { 6047 if (!siteData.faqs) siteData.faqs = { items: [] }; 6048 siteData.faqs.items.push({ 6049 question: 'What are the visa and tuition requirements for Germany?', 6050 answer: 'Public universities in Germany offer tuition-free higher education for international students. Candidates must set up a blocked account (Sperrkonto) to cover living expenses and provide certified transcripts and test scores.' 6051 }); 6052 saveSiteData(siteData); 6053 }; 6054 } 6055 6056 document.querySelectorAll('.btn-delete-faq').forEach(btn => { 6057 btn.onclick = (e) => { 6058 const idx = parseInt(e.currentTarget.dataset.index, 10); 6059 if (!isNaN(idx) && siteData.faqs && siteData.faqs.items) { 6060 siteData.faqs.items.splice(idx, 1); 6061 saveSiteData(siteData); 6062 } 6063 }; 6064 }); 6065 6066 const btnSaveFaqs = document.getElementById('btn-save-faqs'); 6067 if (btnSaveFaqs) { 6068 btnSaveFaqs.onclick = () => { 6069 if (!siteData.faqs) siteData.faqs = { items: [] }; 6070 siteData.faqs.tag = document.getElementById('admin-faq-tag').value; 6071 siteData.faqs.title = document.getElementById('admin-faq-title').value; 6072 siteData.faqs.description = document.getElementById('admin-faq-desc').value; 6073 siteData.faqs.items.forEach((f, i) => { 6074 const q = document.getElementById(`admin-faq-q-${i}`); 6075 if (q) f.question = q.value; 6076 const a = document.getElementById(`admin-faq-a-${i}`); 6077 if (a) f.answer = a.value; 6078 }); 6079 saveSiteData(siteData); 6080 }; 6081 } 6082 6083 // 14. Footer & Social Links 6084 const btnAddQL = document.getElementById('btn-add-quicklink'); 6085 if (btnAddQL) { 6086 btnAddQL.onclick = () => { 6087 if (!siteData.footer) siteData.footer = {}; 6088 if (!siteData.footer.quickLinks) siteData.footer.quickLinks = []; 6089 siteData.footer.quickLinks.push({ name: 'New Link', url: '#' }); 6090 saveSiteData(siteData); 6091 }; 6092 } 6093 6094 document.querySelectorAll('.btn-delete-quicklink').forEach(btn => { 6095 btn.onclick = (e) => { 6096 const idx = parseInt(e.currentTarget.dataset.index, 10); 6097 if (!isNaN(idx) && siteData.footer && siteData.footer.quickLinks) { 6098 siteData.footer.quickLinks.splice(idx, 1); 6099 saveSiteData(siteData); 6100 } 6101 }; 6102 }); 6103 6104 const btnAddCL = document.getElementById('btn-add-countrylink'); 6105 if (btnAddCL) { 6106 btnAddCL.onclick = () => {
6107 if (!siteData.footer) siteData.footer = {}; 6108 if (!siteData.footer.countries) siteData.footer.countries = []; 6109 siteData.footer.countries.push({ name: 'Study in Germany', url: '#destinations' }); 6110 saveSiteData(siteData); 6111 }; 6112 } 6113 6114 document.querySelectorAll('.btn-delete-countrylink').forEach(btn => { 6115 btn.onclick = (e) => { 6116 const idx = parseInt(e.currentTarget.dataset.index, 10); 6117 if (!isNaN(idx) && siteData.footer && siteData.footer.countries) { 6118 siteData.footer.countries.splice(idx, 1); 6119 saveSiteData(siteData); 6120 } 6121 }; 6122 }); 6123 6124 const btnSaveFooter = document.getElementById('btn-save-footer'); 6125 if (btnSaveFooter) { 6126 btnSaveFooter.onclick = () => { 6127 if (!siteData.footer) siteData.footer = {}; 6128 const abtEl = document.getElementById('admin-footer-about'); 6129 if (abtEl) siteData.footer.aboutText = abtEl.value; 6130 const cpyEl = document.getElementById('admin-footer-copy'); 6131 if (cpyEl) siteData.footer.copyright = cpyEl.value; 6132 if (!siteData.footer.social) siteData.footer.social = {}; 6133 const fbEl = document.getElementById('admin-social-fb'); 6134 if (fbEl) siteData.footer.social.facebook = fbEl.value; 6135 const instaEl = document.getElementById('admin-social-insta'); 6136 if (instaEl) siteData.footer.social.instagram = instaEl.value; 6137 const linkEl = document.getElementById('admin-social-linkedin'); 6138 if (linkEl) siteData.footer.social.linkedin = linkEl.value; 6139 const ytEl = document.getElementById('admin-social-yt'); 6140 if (ytEl) siteData.footer.social.youtube = ytEl.value; 6141 6142 if (siteData.footer.quickLinks) { 6143 siteData.footer.quickLinks.forEach((l, i) => { 6144 const n = document.getElementById(`admin-footer-ql-name-${i}`); 6145 if (n) l.name = n.value; 6146 const u = document.getElementById(`admin-footer-ql-url-${i}`); 6147 if (u) l.url = u.value; 6148 }); 6149 } 6150 if (siteData.footer.countries) { 6151 siteData.footer.countries.forEach((c, i) => { 6152 const n = document.getElementById(`admin-footer-c-name-${i}`); 6153 if (n) c.name = n.value; 6154 const u = document.getElementById(`admin-footer-c-url-${i}`); 6155 if (u) c.url = u.value; 6156 }); 6157 } 6158 saveSiteData(siteData); 6159 }; 6160 } 6161 6162 // 15. General Settings & Contact 6163 const btnSaveGen = document.getElementById('btn-save-gen'); 6164 if (btnSaveGen) { 6165 btnSaveGen.onclick = () => { 6166 siteData.general.siteName = document.getElementById('admin-gen-sitename').value; 6167 siteData.general.email = document.getElementById('admin-gen-email').value; 6168 siteData.general.phone = document.getElementById('admin-gen-phone').value; 6169 siteData.general.mobilePhone = document.getElementById('admin-gen-mobile').value; 6170 siteData.general.layoutMode = document.getElementById('admin-gen-layout').value; 6171 siteData.general.address = document.getElementById('admin-gen-address').value; 6172 if (siteData.footer) { 6173 siteData.footer.aboutText = document.getElementById('admin-gen-footer-about').value; 6174 } 6175 // Keep topBar in sync 6176 if (siteData.topBar) { 6177 siteData.topBar.phone = siteData.general.phone; 6178 siteData.topBar.mobile = siteData.general.mobilePhone; 6179 siteData.topBar.email = siteData.general.email; 6180 siteData.topBar.address = siteData.general.address; 6181 } 6182 saveSiteData(siteData); 6183 }; 6184 } 6185 6186 // Filter tabs for Represented Institutions 6187 const instTabBtns = document.querySelectorAll('.inst-tab-btn'); 6188 if (instTabBtns.length > 0) { 6189 instTabBtns.forEach(btn => { 6190 btn.onclick = () => { 6191 instTabBtns.forEach(b => b.classList.remove('active')); 6192 btn.classList.add('active'); 6193 const filter = btn.getAttribute('data-filter'); 6194 const cards = document.querySelectorAll('.inst-card-slide'); 6195 cards.forEach(card => { 6196 if (filter === 'all' || card.getAttribute('data-category') === filter) { 6197 card.style.display = 'block'; 6198 } else { 6199 card.style.display = 'none'; 6200 } 6201 }); 6202 }; 6203 }); 6204 } 6205 6206 // Partner Destination Filter Tabs (All, Australia, USA, UK, Europe, Canada) 6207 const partnerDestTabs = document.querySelectorAll('.partner-dest-tab-btn');
6208 const partnerScrollContainer = document.getElementById('partner-scroll-container'); 6209 6210 if (partnerDestTabs.length > 0 && partnerScrollContainer) { 6211 partnerDestTabs.forEach(btn => { 6212 btn.onclick = () => { 6213 partnerDestTabs.forEach(b => b.classList.remove('active')); 6214 btn.classList.add('active'); 6215 const dest = btn.getAttribute('data-dest'); 6216 partnerScrollContainer.innerHTML = getScrollTrackHtml(dest); 6217 }; 6218 }); 6219 } 6220 6221 // Partner Destination Filter Tabs on B2B Page (#b2b-institutions) 6222 const b2bInstTabs = document.querySelectorAll('.b2b-inst-tab-btn'); 6223 if (b2bInstTabs.length > 0) { 6224 b2bInstTabs.forEach(btn => { 6225 btn.onclick = () => { 6226 b2bInstTabs.forEach(b => b.classList.remove('active')); 6227 btn.classList.add('active'); 6228 const filter = (btn.getAttribute('data-filter') || 'all').toLowerCase(); 6229 const cards = document.querySelectorAll('.b2b-inst-card'); 6230 cards.forEach(card => { 6231 const loc = (card.getAttribute('data-location') || '').toLowerCase(); 6232 if (filter === 'all' || loc === filter) { 6233 card.style.display = 'flex'; 6234 } else { 6235 card.style.display = 'none'; 6236 } 6237 }); 6238 }; 6239 }); 6240 } 6241 6242 // FAQ Accordion Toggle Interaction 6243 const faqButtons = document.querySelectorAll('.faq-question-btn'); 6244 if (faqButtons.length > 0) { 6245 faqButtons.forEach(btn => { 6246 btn.onclick = () => { 6247 const item = btn.closest('.faq-item'); 6248 const panel = item.querySelector('.faq-answer-panel'); 6249 const isOpen = item.classList.contains('active'); 6250 6251 // Close all other items for a clean accordion experience 6252 document.querySelectorAll('.faq-item').forEach(other => { 6253 if (other !== item) { 6254 other.classList.remove('active'); 6255 const otherPanel = other.querySelector('.faq-answer-panel'); 6256 const otherBtn = other.querySelector('.faq-question-btn'); 6257 if (otherPanel) otherPanel.style.display = 'none'; 6258 if (otherBtn) otherBtn.setAttribute('aria-expanded', 'false'); 6259 } 6260 }); 6261 6262 // Toggle clicked item 6263 if (isOpen) { 6264 item.classList.remove('active'); 6265 if (panel) panel.style.display = 'none'; 6266 btn.setAttribute('aria-expanded', 'false'); 6267 } else { 6268 item.classList.add('active'); 6269 if (panel) panel.style.display = 'block'; 6270 btn.setAttribute('aria-expanded', 'true'); 6271 } 6272 }; 6273 }); 6274 } 6275 } 6276 6277 /* Image Lightbox Modal for Official University Slides & Visa Grants */ 6278 window.openImageModal = function(imgSrc, title) { 6279 let modal = document.getElementById('image-lightbox-modal'); 6280 if (!modal) { 6281 modal = document.createElement('div'); 6282 modal.id = 'image-lightbox-modal'; 6283 modal.className = 'lightbox-overlay'; 6284 modal.onclick = function(e) { 6285 if (e.target === modal) closeImageModal(); 6286 }; 6287 document.addEventListener('keydown', function(e) { 6288 if (e.key === 'Escape') closeImageModal(); 6289 }); 6290 document.body.appendChild(modal); 6291 } 6292 modal.innerHTML = ` 6293 <div class="lightbox-container" style="max-width: 600px;"> 6294 <div class="lightbox-header"> 6295 <h3><i class="fa-solid fa-passport"></i> ${title || 'Visa Approval Grant'}</h3> 6296 <button onclick="closeImageModal()" class="lightbox-close-btn">×</button> 6297 </div> 6298 <div class="lightbox-body" style="padding: 16px; background: #00221c; display: flex; justify-content: center;"> 6299 <img src="${imgSrc}" alt="${title}" class="lightbox-img" style="max-height: 80vh; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.5);" /> 6300 </div> 6301 </div> 6302 `; 6303 modal.classList.add('active'); 6304 }; 6305 6306 window.closeImageModal = function() { 6307 const modal = document.getElementById('image-lightbox-modal'); 6308 if (modal) modal.classList.remove('active'); 6309 }; 6310 6311 /* Admin Modal: Directly Add B2B Partner & Assign ID */ 6312 window.openAdminAddPartnerModal = function() { 6313 let modal = document.getElementById('admin-add-partner-modal'); 6314 if (!modal) { 6315 modal = document.createElement('div'); 6316 modal.id = 'admin-add-partner-modal'; 6317 modal.className = 'lightbox-overlay'; 6318 modal.onclick = function(e) { 6319 if (e.target === modal) window.closeAdminAddPartnerModal(); 6320 }; 6321 document.body.appendChild(modal); 6322 } 6323
6324 const defaultSubAgentCode = 'KGN-SA-' + Math.floor(1000 + Math.random() * 9000); 6325 6326 modal.innerHTML = ` 6327 <div class="lightbox-container" style="max-width: 580px; background: #ffffff; border-radius: 16px; overflow: hidden; box-shadow: 0 20px 50px rgba(0,0,0,0.3); border: 1px solid #d0dfdc;"> 6328 <div class="lightbox-header" style="background: linear-gradient(135deg, #00332a, #004a3e); color: #fff; padding: 18px 24px; display: flex; justify-content: space-between; align-items: center;"> 6329 <div> 6330 <h3 style="margin: 0; font-size: 17px; font-weight: 800; color: #ffffff; display: flex; align-items: center; gap: 8px;"> 6331 <i class="fa-solid fa-user-plus"></i> Add Partner & Assign Portal ID 6332 </h3> 6333 <p style="margin: 4px 0 0; font-size: 11.5px; color: #a3e635;">Assign a custom secure ID for direct B2B student file dispatch</p> 6334 </div> 6335 <button onclick="window.closeAdminAddPartnerModal()" style="background: rgba(255,255,255,0.15); border: none; color: #fff; width: 32px; height: 32px; border-radius: 50%; cursor: pointer; font-size: 16px;">×</button> 6336 </div> 6337 <form id="admin-create-partner-form" style="padding: 24px; display: flex; flex-direction: column; gap: 14px; max-height: 80vh; overflow-y: auto;"> 6338 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;"> 6339 <div> 6340 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Partner Type *</label> 6341 <select id="modal-add-type" style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px;"> 6342 <option value="sub-agent">Sub-Agent / Regional Partner</option> 6343 <option value="university">University / College Representative</option> 6344 </select> 6345 </div> 6346 <div> 6347 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Initial Status</label> 6348 <select id="modal-add-status" style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px;"> 6349 <option value="approved">Approved & Active</option> 6350 <option value="pending">Pending Review</option> 6351 </select> 6352 </div> 6353 </div> 6354 6355 <div style="background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 12px;"> 6356 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px;"> 6357 <label style="font-size: 12px; font-weight: 800; color: #0f172a;">Assigned Partner ID / Access Code *</label> 6358 <button type="button" id="btn-gen-code-subagent" style="background: #e2e8f0; border: none; padding: 3px 8px; border-radius: 4px; font-size: 10.5px; font-weight: 700; color: #334155; cursor: pointer;"> 6359 <i class="fa-solid fa-wand-magic-sparkles"></i> Auto Gen 6360 </button> 6361 </div> 6362 <input type="text" id="modal-add-code" value="${defaultSubAgentCode}" placeholder="e.g. KGN-SA-1025 or APEX-2026" required style="width: 100%; padding: 8px 12px; border: 2px solid #004a3e; border-radius: 6px; font-size: 13.5px; font-family: monospace; font-weight: 800; color: #004a3e; text-transform: uppercase; box-sizing: border-box;" /> 6363 <small style="color: #64748b; font-size: 11px; display: block; margin-top: 4px;">The partner will enter this ID to unlock the B2B Document Dispatcher.</small> 6364 </div> 6365 6366 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;"> 6367 <div> 6368 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Contact Person Name *</label> 6369 <input type="text" id="modal-add-name" placeholder="e.g. Ramesh Shrestha" required style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; box-sizing: border-box;" /> 6370 </div> 6371 <div> 6372 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">
6372Agency / Institution Name *</label> 6373 <input type="text" id="modal-add-company" placeholder="e.g. Apex Global Education" required style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; box-sizing: border-box;" /> 6374 </div> 6375 </div> 6376 6377 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;"> 6378 <div> 6379 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Official Email *</label> 6380 <input type="email" id="modal-add-email" placeholder="e.g. [email protected]" required style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; box-sizing: border-box;" /> 6381 </div> 6382 <div> 6383 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Phone / WhatsApp *</label> 6384 <input type="tel" id="modal-add-phone" placeholder="e.g. +977 9801234567" required style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; box-sizing: border-box;" /> 6385 </div> 6386 </div> 6387 6388 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;"> 6389 <div> 6390 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Location / City</label> 6391 <input type="text" id="modal-add-location" placeholder="e.g. Pokhara, Nepal" style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; box-sizing: border-box;" /> 6392 </div> 6393 <div> 6394 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Expected Annual Volume</label> 6395 <input type="text" id="modal-add-volume" placeholder="e.g. 20-50 Students / Year" style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; box-sizing: border-box;" /> 6396 </div> 6397 </div> 6398 6399 <div> 6400 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Internal Notes / Partnership Scope</label> 6401 <textarea id="modal-add-notes" placeholder="e.g. Authorized partner for Western Region. Handles USA & Germany admissions." style="width: 100%; height: 55px; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 12.5px; box-sizing: border-box;"></textarea> 6402 </div> 6403 6404 <div id="modal-add-error" style="color: #dc2626; font-size: 12px; font-weight: 600; display: none;"></div> 6405 6406 <div style="display: flex; justify-content: flex-end; gap: 10px; margin-top: 10px;"> 6407 <button type="button" onclick="window.closeAdminAddPartnerModal()" style="background: #f1f5f9; color: #475569; border: 1px solid #cbd5e1; padding: 9px 16px; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer;">Cancel</button> 6408 <button type="submit" id="btn-submit-add-partner" style="background: linear-gradient(135deg, #004a3e, #006b5b); color: #fff; border: none; padding: 9px 20px; border-radius: 8px; font-size: 13px; font-weight: 700; cursor: pointer; display: flex; align-items: center; gap: 6px;"> 6409 <i class="fa-solid fa-check"></i> Save & Assign ID 6410 </button> 6411 </div> 6412 </form> 6413 </div> 6414 `; 6415 6416 document.getElementById('modal-add-code').oninput = function(e) { 6417 e.target.value = e.target.value.toUpperCase(); 6418 }; 6419 6420 document.getElementById('btn-gen-code-subagent').onclick = function() { 6421 const type = document.getElementById('modal-add-type').value; 6422 const prefix = type === 'university' ? 'KGN-EDU-' : 'KGN-SA-'; 6423 document.getElementById('modal-add-code').value = prefix + Math.floor(1000 + Math.random() * 9000); 6424 }; 6425 6426 document.getElementById('modal-add-type').onchange = function(e) { 6427 const prefix = e.target.value === 'university' ? 'KGN-EDU-' : 'KGN-SA-'; 6428 const curr = document.getElementById('modal-add-code').value; 6429 if (curr.startsWith('KGN-SA-') || curr.startsWith('KGN-EDU-')) { 6430 document.getElementById('modal-add-code').value = prefix + Math.floor(1000 + Math.random() * 9000); 6431 } 6432 }; 6433 6434 document.getElementById('admin-create-partner-form').onsubmit = async function(e) { 6435 e.preventDefault(); 6436 const errEl = document.getElementById('modal-add-error'); 6437 errEl.style.display = 'none'; 6438 6439 const payload = { 6440 partnerType: document.getElementById('modal-add-type').value, 6441 partnerCode: document.getElementById('modal-add-code').value.trim().toUpperCase(), 6442 status: document.getElementById('modal-add-status').value, 6443 name: document.getElementById('modal-add-name').value.trim(), 6444 company: document.getElementById('modal-add-company').value.trim(), 6445 email: document.getElementById('modal-add-email').value.trim(), 6446 phone: document.getElementById('modal-add-phone').value.trim(), 6447 location: document.getElementById('modal-add-location').value.trim(), 6448 studentVolume: document.getElementById('modal-add-volume').value.trim(), 6449 message: document.getElementById('modal-add-notes').value.trim() 6450 }; 6451 6452 const result = await createPartnerApp(payload); 6453 if (result.success) { 6454 window.closeAdminAddPartnerModal(); 6455 alert(`â Partner created successfully!\nAssigned ID: ${result.partner.partnerCode}`); 6456 } else { 6457 errEl.textContent = result.message || 'Error creating partner.'; 6458 errEl.style.display = 'block'; 6459 } 6460 }; 6461 6462 modal.classList.add('active'); 6463 }; 6464 6465 window.closeAdminAddPartnerModal = function() { 6466 const modal = document.getElementById('admin-add-partner-modal'); 6467 if (modal) modal.classList.remove('active'); 6468 }; 6469 6470 /* Admin Modal: Edit Partner Details & Re-assign ID */ 6471 window.openAdminEditPartnerModal = function(partnerId) { 6472 const partner = partnerApps.find(p => p.id === partnerId); 6473 if (!partner) return; 6474 6475 let modal = document.getElementById('admin-edit-partner-modal'); 6476 if (!modal) { 6477 modal = document.createElement('div'); 6478 modal.id = 'admin-edit-partner-modal'; 6479 modal.className = 'lightbox-overlay'; 6480 modal.onclick = function(e) { 6481 if (e.target === modal) window.closeAdminEditPartnerModal(); 6482 }; 6483 document.body.appendChild(modal); 6484 } 6485 6486 const currentCode = partner.partnerCode || partner.id; 6487 6488 modal.innerHTML = ` 6489 <div class="lightbox-container" style="max-width: 580px; background: #ffffff; border-radius: 16px; overflow: hidden; box-shadow: 0 20px 50px rgba(0,0,0,0.3); border: 1px solid #d0dfdc;"> 6490 <div class="lightbox-header" style="background: linear-gradient(135deg, #00332a, #004a3e); color: #fff; padding: 18px 24px; display: flex; justify-content: space-between; align-items: center;"> 6491 <div> 6492 <h3 style="margin: 0; font-size: 17px; font-weight: 800; color: #ffffff; display: flex; align-items: center; gap: 8px;"> 6493 <i class="fa-solid fa-pen-to-square"></i> Edit Partner & Re-assign ID 6494 </h3> 6495 <p style="margin: 4px 0 0; font-size: 11.5px; color: #a3e635;">${partner.name} ⢠${partner.company || 'Partner'}</p> 6496 </div> 6497 <button onclick="window.closeAdminEditPartnerModal()" style="background: rgba(255,255,255,0.15); border: none; color: #fff; width: 32px; height: 32px; border-radius: 50%; cursor: pointer; font-size: 16px;">×</button> 6498 </div> 6499 <form id="admin-edit-partner-form" style="padding: 24px; display: flex; flex-direction: column; gap: 14px; max-height: 80vh; overflow-y: auto;"> 6500 <div style="background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px; padding: 12px;"> 6501 <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px;"> 6502 <label style="font-size: 12px; font-weight: 800; color: #166534;">Assigned Partner ID / Access Code *</label> 6503 <button type="button" id="btn-edit-gen-code" style="background: #dcfce7; border: 1px solid #bbf7d0; padding: 3px 8px; border-radius: 4px; font-size: 10.5px; font-weight: 700; color: #15803d; cursor: pointer;"> 6504 <i class="fa-solid fa-wand-magic-sparkles"></i> Auto Gen 6505 </button> 6506 </div> 6507 <input type="text" id="modal-edit-code" value="${currentCode}" required style="width: 100%; padding: 8px 12px; border: 2px solid #16a34a; border-radius: 6px; font-size: 14px; font-family: monospace; font-weight: 800; color: #14532d; text-transform: uppercase; box-sizing: border-box;" /> 6508 <small style="color: #4b5563; font-size: 11px; display: block; margin-top: 4px;">Update this code anytime. The partner will instantly unlock the B2B portal using this ID.</small> 6509 </div> 6510 6511 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;"> 6512 <div> 6513 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Partner Status</label> 6514 <select id="modal-edit-status" style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px;"> 6515 <option value="approved" ${partner.status === 'approved' ? 'selected' : ''}>Approved & Active</option> 6516 <option value="pending" ${partner.status === 'pending' ? 'selected' : ''}>Pending Review</option> 6517 <option value="rejected" ${partner.status === 'rejected' ? 'selected' : ''}>Declined / Inactive</option> 6518 </select> 6519 </div> 6520 <div> 6521 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Partner Type</label> 6522 <select id="modal-edit-type" style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px;"> 6523 <option value="sub-agent" ${partner.partnerType === 'sub-agent' ? 'selected' : ''}>Sub-Agent / Regional Partner</option> 6524 <option value="university" ${partner.partnerType === 'university' ? 'selected' : ''}>University / College Representative</option> 6525 </select> 6526 </div> 6527 </div> 6528 6529 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;"> 6530 <div> 6531 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Contact Person Name *</label> 6532 <input type="text" id="modal-edit-name" value="${partner.name || ''}" required style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; box-sizing: border-box;" /> 6533 </div> 6534 <div> 6535 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">
6535Agency / Institution Name *</label> 6536 <input type="text" id="modal-edit-company" value="${partner.company || ''}" required style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; box-sizing: border-box;" /> 6537 </div> 6538 </div> 6539 6540 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;"> 6541 <div> 6542 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Official Email *</label> 6543 <input type="email" id="modal-edit-email" value="${partner.email || ''}" required style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; box-sizing: border-box;" /> 6544 </div> 6545 <div> 6546 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Phone / WhatsApp *</label> 6547 <input type="tel" id="modal-edit-phone" value="${partner.phone || ''}" required style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; box-sizing: border-box;" /> 6548 </div> 6549 </div> 6550 6551 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;"> 6552 <div> 6553 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Location / City</label> 6554 <input type="text" id="modal-edit-location" value="${partner.location || ''}" style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; box-sizing: border-box;" /> 6555 </div> 6556 <div> 6557 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Expected Volume</label> 6558 <input type="text" id="modal-edit-volume" value="${partner.studentVolume || ''}" style="width: 100%; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 13px; box-sizing: border-box;" /> 6559 </div> 6560 </div> 6561 6562 <div> 6563 <label style="display: block; font-size: 12px; font-weight: 700; color: #00332a; margin-bottom: 4px;">Notes / Remarks</label> 6564 <textarea id="modal-edit-notes" style="width: 100%; height: 55px; padding: 8px 10px; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 12.5px; box-sizing: border-box;">${partner.message || ''}</textarea> 6565 </div> 6566 6567 <div id="modal-edit-error" style="color: #dc2626; font-size: 12px; font-weight: 600; display: none;"></div> 6568 6569 <div style="display: flex; justify-content: flex-end; gap: 10px; margin-top: 10px;"> 6570 <button type="button" onclick="window.closeAdminEditPartnerModal()" style="background: #f1f5f9; color: #475569; border: 1px solid #cbd5e1; padding: 9px 16px; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer;">Cancel</button> 6571 <button type="submit" id="btn-submit-edit-partner" style="background: linear-gradient(135deg, #004a3e, #006b5b); color: #fff; border: none; padding: 9px 20px; border-radius: 8px; font-size: 13px; font-weight: 700; cursor: pointer; display: flex; align-items: center; gap: 6px;"> 6572 <i class="fa-solid fa-save"></i> Update Partner & ID 6573 </button> 6574 </div> 6575 </form> 6576 </div> 6577 `; 6578 6579 document.getElementById('modal-edit-code').oninput = function(e) { 6580 e.target.value = e.target.value.toUpperCase(); 6581 }; 6582 6583 document.getElementById('btn-edit-gen-code').onclick = function() { 6584 const type = document.getElementById('modal-edit-type').value; 6585 const prefix = type === 'university' ? 'KGN-EDU-' : 'KGN-SA-'; 6586 document.getElementById('modal-edit-code').value = prefix + Math.floor(1000 + Math.random() * 9000); 6587 }; 6588 6589 document.getElementById('admin-edit-partner-form').onsubmit = async function(e) { 6590 e.preventDefault(); 6591 const errEl = document.getElementById('modal-edit-error'); 6592 errEl.style.display = 'none'; 6593 6594 const payload = { 6595 partnerType: document.getElementById('modal-edit-type').value, 6596 partnerCode: document.getElementById('modal-edit-code').value.trim().toUpperCase(), 6597 status: document.getElementById('modal-edit-status').value, 6598 name: document.getElementById('modal-edit-name').value.trim(), 6599 company: document.getElementById('modal-edit-company').value.trim(), 6600 email: document.getElementById('modal-edit-email').value.trim(), 6601 phone: document.getElementById('modal-edit-phone').value.trim(), 6602 location: document.getElementById('modal-edit-location').value.trim(), 6603 studentVolume: document.getElementById('modal-edit-volume').value.trim(), 6604 message: document.getElementById('modal-edit-notes').value.trim() 6605 }; 6606 6607 const result = await updatePartnerApp(partnerId, payload); 6608 if (result.success) { 6609 window.closeAdminEditPartnerModal(); 6610 alert(`â Partner ID updated to: ${result.partner.partnerCode}`); 6611 } else { 6612 errEl.textContent = result.message || 'Error updating partner.'; 6613 errEl.style.display = 'block'; 6614 } 6615 }; 6616 6617 modal.classList.add('active'); 6618 }; 6619 6620 window.closeAdminEditPartnerModal = function() { 6621 const modal = document.getElementById('admin-edit-partner-modal'); 6622 if (modal) modal.classList.remove('active'); 6623 }; 6624 6625 window.addEventListener('hashchange', renderApp); 6626 window.addEventListener('popstate', renderApp); 6627 loadData(); 6628 loadSubmissions(); 6629 loadPartnerApps(); 6630})();
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.