1const pathSegment = window.location.pathname.split('/').pop(); 2const usableWebinarId = pathSegment?.split("-").slice(-1)[0]; 3 4const currentOrg = getCurrentOrg(); 5 6let countdownInterval = null; 7 8document.addEventListener('alpine:init', () => { 9 Alpine.store('webinarStore', { 10 webinar: null, 11 hero: null, 12 hosts: null, 13 testimonials: null, 14 outcomes: null, 15 loading: false, 16 promise: null, 17 state: null, 18 isLoggedIn: false, 19 20 async fetch() { 21 this.loading = true; 22 23 try { 24 25 if (isPreviewMode()) { 26 const { webinar, hero, outcomes, testimonials, hosts } = getMockWebinarData(); 27 this.webinar = webinar; 28 this.hero = hero; 29 this.outcomes = outcomes; 30 this.testimonials = testimonials; 31 this.hosts = hosts; 32 return; 33 } 34 35 const response = await fetch(`/t/api/content/public/livesession/get/${usableWebinarId}?orgId=${currentOrg._id}`); 36 const data = await response.json(); 37 const isLive = data?.sessionStatus === WEBINAR_STATUS.LIVE; 38 39 this.webinar = data; 40 this.hero = normalizeHeroData(data); 41 this.outcomes = normalizeOutcomesData(data); 42 this.testimonials = normalizeTestimonialsData(data); 43 this.hosts = normalizeHostsData(data); 44 45 const { isWithin24Hrs } = webinarUtils.getTimeUntilStart(data?.startTime); 46 if (isWithin24Hrs && !isLive) { 47 this.startCountdown(); 48 } 49 50 } catch (err) { 51 console.error(err); 52 } finally { 53 this.loading = false; 54 } 55 }, 56 57 startCountdown() { 58 if (countdownInterval) clearInterval(countdownInterval); 59 60 countdownInterval = setInterval(() => { 61 if (!this.webinar) return; 62 63 const { isWithin24Hrs, countDownWithSeconds } = webinarUtils.getTimeUntilStart(this.webinar.startTime); 64 65 if (isWithin24Hrs) { 66 this.hero = { ...this.hero, statusBadgeText: countDownWithSeconds }; 67 } else { 68 clearInterval(countdownInterval); 69 countdownInterval = null; 70 this.hero = { ...this.hero, ...getWebinarStatusBadge(this.webinar) }; 71 } 72 }, 1000); 73 }, 74 75 handleActionButtonClick() { 76 if (isPreviewMode()) return; 77 78 const webinar = { ...this.webinar }; 79 const actionType = getButtonText(webinar).actionType; 80 const isLoggedIn = this.isLoggedIn; 81 82 switch (actionType) { 83 case "register": 84 handleRegisterAction(webinar); 85 break; 86 case "joinCommunity": 87 handleJoinCommunityAction(webinar); 88 break; 89 case "getNotified": 90 handleGetNotifiedAction(webinar, isLoggedIn); 91 break; 92 case "joinWebinar": 93 handleJoinWebinarAction(webinar); 94 break; 95 case "watchRecording": 96 handleWatchRecordingAction(webinar); 97 break; 98 default: 99 // No action required for unknown actionTypes 100 break; 101 } 102 } 103 }); 104 105 // â Global fetch (runs once) 106 Alpine.store('webinarStore').fetch(); 107}); 108 109function normalizeHeroData(data) { 110 const status = getWebinarStatusBadge(data); 111 const { currency = "INR", mrp = 0, price = 0 } = data; 112 113 return { 114 title: data.title, 115 statusBadgeText: status.statusBadgeText, 116 statusBadgeBg: status.statusBadgeBg, 117 coverImage: getCoverImageUrl(data.coverPath), 118 formattedDateTime: webinarUtils.getFormattedDateTime(data.startTime, data.endTime), 119 meetingType: data.type === "webinarV2" ? "Graphy Live Meeting" : "Zoom Meeting", 120 description: data.description, 121 actionButtonText: getButtonText(data).buttonText, 122 actionButtonSubTitle: getButtonText(data).subTitle, 123 mrpLabel: mrp && mrp > price ? getDisplayAmount(mrp, currency) : null, 124 priceLabel: price === 0 ? 'FREE' : getDisplayAmount(price, currency), 125 }; 126} 127 128function normalizeOutcomesData(data) { 129 const mapIcon = (icon) => { 130 return IconsNameToUnicodeMapping[icon] || 'lightbulb'; 131 }; 132 133 const validOutcomes = (data.outcomes || []) 134 .filter(o => o && o.title && o.title.trim() !== '') 135 .map((o) => ({ 136 title: o.title, 137 description: o.description || '', 138 icon: mapIcon(o.icon) 139 })); 140 return validOutcomes; 141} 142 143function normalizeTestimonialsData(data) { 144 const validTestimonials = (data.testimonials || []) 145 .filter(t => t && t.name && t.name.trim() !== '' && t.testimonial && t.testimonial.trim() !== '') 146 .map((t) => ({ 147 name: t.name, 148 text: t.testimonial, 149 role: t.designation || '', 150 avatar: getProfileImageUrl(t.profilePicPath) 151 })); 152 return validTestimonials; 153} 154 155function normalizeHostsData(data) { 156 const validHosts = (data.hosts || []) 157 .filter(h => h && h.name && h.name.trim() !== '') 158 .map((h) => ({ 159 name: h.name, 160 bio: h.bio || '', 161 title: h.designation || '', 162 avatar: getProfileImageUrl(h.profilePicPath) 163 })); 164 return validHosts; 165} 166 167function getButtonText(webinar) { 168 if ("startTime" in webinar) { 169 const webinarCurrentState = webinarUtils.getWebinarCurrentState(webinar); 170 const userRegistered = webinar.userRegistered; 171 const TEN_MINS_PRIOR = webinarCurrentState === "10_MINS_PRIOR"; 172 const TODAY_24_HRS_PRIOR = webinarCurrentState === "24_HRS_PRIOR"; 173 const sessionHappenedRecordingAvailable = 174 webinarCurrentState === "PAST_AND_RECORDED"; 175 const sessionHappenedRecordingUnavailable = 176 webinarCurrentState === "PAST_AND_NOT_RECORDED"; 177 const conducted = webinar.sessionStatus === WEBINAR_STATUS.ENDED; 178 179 const isLive = webinar.sessionStatus === WEBINAR_STATUS.LIVE; 180 const loggedIn = localStorage.getItem("microserviceAuthToken"); 181 182 const isBatchFull = webinar.registrations === webinar.batchSize; 183 const expired = webinar.sessionStatus === WEBINAR_STATUS.EXPIRED; 184 185 if (webinar.isPaid) { 186 if (loggedIn) { 187 if (userRegistered) { 188 if (sessionHappenedRecordingAvailable) { 189 return { 190 buttonText: "Watch webinar recording", 191 subTitle: "Learn at your own pace", 192 actionType: "watchRecording", 193 }; 194 } 195 if (isLive) { 196 return { 197 buttonText: "Join Now", 198 subTitle: "", 199 actionType: "joinWebinar" 200 }; 201 } 202 if (expired) { 203 return { 204 buttonText: "", 205 subTitle: "", 206 }; 207 } 208 return { 209 buttonText: "Claim your invite to the community", 210 subTitle: "Start learning with members", 211 actionType: "joinCommunity", 212 }; 213 } else { 214 if (isBatchFull) { 215 return { 216 buttonText: "Get notified for upcoming webinars", 217 subTitle: "Batch size is full", 218 actionType: "getNotified", 219 }; 220 } 221 if (sessionHappenedRecordingAvailable) { 222 return { 223 buttonText: "Buy webinar recording", 224 subTitle: "Learn at your own pace", 225 actionType: "register", 226 }; 227 } 228 if (TODAY_24_HRS_PRIOR) { 229 return { 230 buttonText: "Register", 231 subTitle: "Seat almost full!", 232 actionType: "register", 233 }; 234 } 235 if (isLive) { 236 return { 237 buttonText: "Register", 238 subTitle: "Hurry, webinar in progress!", 239 actionType: "register", 240 }; 241 } 242 243 if (expired) { 244 return { 245 buttonText: "", 246 subTitle: "", 247 }; 248 } 249 250 return { 251 buttonText: "Register", 252 subTitle: "Limited seats only!", 253 actionType: "register", 254 }; 255 } 256 } else { 257 if (isBatchFull) { 258 return { 259 buttonText: "Get notified for upcoming webinars", 260 subTitle: "Batch size is full", 261 actionType: "getNotified", 262 }; 263 } 264 if (sessionHappenedRecordingAvailable) { 265 return { 266 buttonText: "Buy webinar recording", 267 subTitle: "Learn at your own pace", 268 actionType: "register", 269 }; 270 } 271 272 if (TODAY_24_HRS_PRIOR) { 273 return { 274 buttonText: "Register", 275 subTitle: "Seat almost full!", 276 actionType: "register", 277 }; 278 } 279 280 if (expired) { 281 return { 282 buttonText: "", 283 subTitle: "", 284 }; 285 } 286 287 return { 288 buttonText: "Register", 289 subTitle: "Limited seats only!", 290 actionType: "register", 291 }; 292 } 293 } else { 294 if (loggedIn) { 295 if (userRegistered) { 296 if (sessionHappenedRecordingAvailable) { 297 return { 298 buttonText: "Watch webinar recording", 299 subTitle: "Learn at your own pace", 300 actionType: "watchRecording", 301 }; 302 } 303 304 if (isLive) { 305 return { 306 buttonText: "Join Now", 307 subTitle: "", 308 actionType: "joinWebinar", 309 }; 310 } 311 if (expired) { 312 return { 313 buttonText: "", 314 subTitle: "", 315 }; 316 } 317 return { 318 buttonText: "Claim your invite to the community", 319 subTitle: "Start learning with members", 320 actionType: "joinCommunity", 321 }; 322 } else { 323 if (sessionHappenedRecordingAvailable) { 324 return { 325 buttonText: "Access recording for free", 326 subTitle: "Learn at your own pace", 327 actionType: "register", 328 }; 329 } 330 if (isBatchFull) { 331 return { 332 buttonText: "Get notified for upcoming webinars", 333 subTitle: "Batch size is full", 334 actionType: "getNotified", 335 }; 336 } 337 if (expired) { 338 return { 339 buttonText: "", 340 subTitle: "", 341 }; 342 } 343 return { 344 buttonText: "Claim your free seat", 345 subTitle: "", 346 actionType: "register", 347 }; 348 } 349 } else { 350 if (isBatchFull) { 351 return { 352 buttonText: "Get notified for upcoming webinars", 353 subTitle: "Batch size is full", 354 actionType: "getNotified", 355 }; 356 } 357 if (isLive) { 358 return { 359 buttonText: "Join Now", 360 subTitle: "Hurry, webinar in progress!", 361 actionType: "register", 362 }; 363 } 364 365 if (TODAY_24_HRS_PRIOR) { 366 return { 367 buttonText: "Claim your free seat", 368 subTitle: "It's your last chance!", 369 actionType: "register", 370 }; 371 } 372 if (sessionHappenedRecordingAvailable) { 373 return { 374 buttonText: "Access recording for free", 375 subTitle: "Learn at your own pace", 376 actionType: "register", 377 }; 378 } 379 if (conducted && sessionHappenedRecordingUnavailable) { 380 return { 381 buttonText: "Sign up to never miss an update", 382 subTitle: "", 383 actionType: "getNotified", 384 }; 385 } 386 if (expired) { 387 return { 388 buttonText: "", 389 subTitle: "", 390 }; 391 } 392 return { 393 buttonText: "Claim your free seat", 394 subTitle: "Before it's too late!", 395 actionType: "register", 396 }; 397 } 398 } 399 } 400 return { 401 buttonText: "Claim your free seat", 402 subTitle: "", 403 actionType: "register", 404 }; 405} 406 407async function getAuthenticatedWebinar(webinarId) { 408 const authToken = localStorage.getItem("microserviceAuthToken"); 409 const response = await fetch(
410 `/t/api/content/livesession/get/${webinarId}?orgId=${currentOrg._id}`, 411 { headers: { 'Authorization': authToken } } 412 ); 413 const data = await response.json(); 414 return data; 415} 416 417window.addEventListener('currentUserUpdated', (event) => { 418 if (isPreviewMode()) return; 419 const currentUser = event.detail; 420 const store = Alpine.store('webinarStore'); 421 if (store) { 422 getAuthenticatedWebinar(store.webinar.id).then(data => { 423 store.webinar = data; 424 store.hero = normalizeHeroData(data); 425 store.isLoggedIn = true; 426 }); 427 } 428}); 429 430function getMockWebinarData() { 431 const mockWebinar = getMockProducts()?.webinars?.[0] || {}; 432 const vHero = createVariableResolver(isVariableMode(), 'store.hero'); 433 const vHost = createVariableResolver(isVariableMode(), 'store.host'); 434 const vTestimonial = createVariableResolver(isVariableMode(), 'store.testimonial'); 435 const vOutcome = createVariableResolver(isVariableMode(), 'store.outcome'); 436 437 return { 438 webinar: mockWebinar, 439 hero: { 440 title: vHero('title', mockWebinar.title), 441 statusBadgeText: vHero('statusBadgeText', 'Upcoming'), 442 statusBadgeBg: '#6C63FF', 443 coverImage: mockWebinar.image_url || getCdnUrl() + mockWebinar.image_path, 444 formattedDateTime: vHero('formattedDateTime', 'Saturday, 10 May 2026 · 6:00 PM â 8:00 PM IST'), 445 meetingType: vHero('meetingType', 'Graphy Live Meeting'), 446 description: vHero('description', mockWebinar.description), 447 actionButtonText: vHero('actionButtonText', 'Register Now'), 448 actionButtonSubTitle: vHero('actionButtonSubTitle', 'Limited seats available'), 449 mrpLabel: vHero('mrpLabel', getDisplayAmount(mockWebinar.mrp, "INR")), 450 priceLabel: vHero('priceLabel', getDisplayAmount(mockWebinar.price, "INR")), 451 }, 452 453 hosts: [ 454 { 455 name: 'Ananya Sharma', 456 title: 'Senior Frontend Engineer', 457 bio: 'Ananya has 8+ years of experience building scalable web applications at top tech companies.', 458 avatar: '', 459 }, 460 { 461 name: 'Rohan Mehta', 462 title: 'Full Stack Developer & Educator', 463 bio: 'Rohan is a passionate educator who has trained over 10,000 developers across India.', 464 avatar: '', 465 }, 466 ].map(h => ({ 467 ...h, 468 name: vHost('name', h.name), 469 bio: vHost('bio', h.bio), 470 title: vHost('title', h.title), 471 })), 472 473 testimonials: [ 474 { 475 name: 'Priya Kapoor', 476 role: 'Frontend Developer', 477 text: 'This webinar completely changed how I think about performance optimisation. Absolutely worth every minute!', 478 avatar: '', 479 }, 480 { 481 name: 'Arjun Nair', 482 role: 'Software Engineer', 483 text: 'The hands-on examples were brilliant. I walked away with actionable techniques I could apply the very next day.', 484 avatar: '', 485 }, 486 { 487 name: 'Sneha Iyer', 488 role: 'UX Engineer', 489 text: 'Incredibly well-structured session. The hosts made complex concepts feel simple and approachable.', 490 avatar: '', 491 }, 492 ].map(t => ({ 493 ...t, 494 name: vTestimonial('name', t.name), 495 role: vTestimonial('role', t.role), 496 text: vTestimonial('text', t.text), 497 })), 498 499 outcomes: [ 500 { title: 'Build Scalable UIs', description: 'Learn component architecture patterns used by top engineering teams.', icon: IconsNameToUnicodeMapping.OutlineFilesBook }, 501 { title: 'Optimise Performance', description: 'Identify and fix bottlenecks to deliver blazing-fast user experiences.', icon: IconsNameToUnicodeMapping.OutlineDevicesCamera }, 502 { title: 'Master Modern Tooling', description: 'Get hands-on with the latest build tools, frameworks, and workflows.', icon: IconsNameToUnicodeMapping.OutlineDevicesDesktop }, 503 { title: 'Career Growth', description: 'Understand what top companies look for and how to stand out.', icon: IconsNameToUnicodeMapping.OutlineGeneralBag }, 504 505 ].map(o => ({ 506 ...o, 507 title: vOutcome('title', o.title), 508 description: vOutcome('description', o.description), 509 })), 510 }; 511} 512 513const IconsNameToUnicodeMapping = { 514 OutlineCommunicationBullhorn: '\ue9b3', 515 OutlineCommunicationChat: '\ue9b4', 516 OutlineCommunicationComment: '\ue9b8', 517 OutlineCommunicationEnvelope: '\ue9bc', 518 OutlineCommunicationForward: '\ue9bd', 519 OutlineCommunicationLike: '\ue9be', 520 OutlineCommunicationPhone: '\ue9c3', 521 OutlineCommunicationReply: '\ue9c4', 522 OutlineCommunicationSend: '\ue9c5', 523 // 524 OutlineCommunicationShare: '\ue9c7', 525 OutlineCommunicationUser: '\ue9cb', 526 OutlineCommunicationUserPlus: '\ue9ca', 527 OutlineDevicesBatteryFull: '\ue9a1', 528 OutlineDevicesCamera: '\ue9a7', 529 OutlineDevicesDesktop: '\ue9a8', 530 OutlineDevicesGamepad: '\ue9aa', 531 OutlineDevicesMobilePhone: '\ue9ab', 532 OutlineDevicesMouseAlt: '\ue9ac', 533 // 534 OutlineDevicesPrinter: '\ue9ae', 535 OutlineStatusUniversity: '\ue923', 536 OutlineDevicesVideo: '\ue9b1', 537 OutlineDevicesWatch: '\ue9b2', 538 OutlineFilesBook: '\ue986', 539 OutlineFilesBookMark: '\ue985', 540 OutlineFilesClipboard: '\ue988', 541 OutlineFilesCloud: '\ue98d', 542 OutlineFilesCloudCheck: '\ue989', 543 // 544 OutlineFilesCloudDownload: '\ue98a', 545 OutlineFilesCloudUpload: '\ue98c', 546 OutlineFilesDocument: '\ue98f', 547 OutlineFilesFiles: '\ue994', 548 OutlineFilesFileUser: '\ue993', 549 OutlineFilesFolder: '\ue99b', 550 OutlineFilesPicture: '\ue99e', 551 OutlineStatusLightbulb: '\ue912', 552 OutlineStatusPresent: '\ue91c', 553 // 554 OutlineGeneralAlarm: '\ue96c', 555 OutlineGeneralBag: '\ue96d', 556 OutlineGeneralBank: '\ue96e', 557 OutlineGeneralCalendar: '\ue970', 558 OutlineGeneralCard: '\ue971', 559 OutlineGeneralChartPieAlt: '\ue972', 560 OutlineGeneralClock: '\ue974', 561 OutlineGeneralFlaskAlt: '\ue976', 562 OutlineGeneralHome: '\ue978', 563 // 564 OutlineGeneralPalette: '\ue97b', 565 OutlineGeneralPulse: '\ue97c', 566 OutlineGeneralSun: '\ue980', 567 OutlineGeneralShoppingBag: '\ue97d', 568 OutlineGeneralUmbrella: '\ue982', 569 OutlineGeneralWallet: '\ue983', 570 OutlineInterfaceCheck: '\ue94c', 571 OutlineInterfaceHotspot: '\ue956', 572 OutlineInterfaceLayout: '\ue957', 573 // 574 OutlineMediaFastForward: '\ue92e', 575 OutlineMediaHeadphone: '\ue930', 576 OutlineMediaMicrophone: '\ue933', 577 OutlineMediaMusic: '\ue934', 578 OutlineMediaShuffle: '\ue937', 579 OutlineMediaVolumeUp: '\ue93c', 580 OutlineNavigationExplore: '\ue926', 581 OutlineNavigationGlobe: '\ue927', 582 OutlineNavigationLocation: '\ue92b', 583 // 584 OutlineStatusAward: '\ue900', 585 OutlineStatusBookOpen: '\ue901', 586 OutlineStatusBookmark: '\ue902', 587 OutlineStatusDiamond: '\ue904', 588 OutlineStatusFire: '\ue907', 589 OutlineStatusHeart: '\ue90a', 590 OutlineStatusEye: '\ue906', 591 OutlineStatusInfoCircle: '\ue90c', 592 OutlineStatusKey: '\ue90f' 593} 594 595function handleRegisterAction(webinar) { 596 const fullUrl = `/t/p/checkout/V4/webinar/${webinar.id}/p1?callback_url=${encodeURIComponent( 597 window.location.pathname 598 )}` 599 window.location.href = fullUrl; 600} 601 602function handleJoinCommunityAction(webinar) { 603 const communityUrl = webinar.communityUrl || '/s/community'; 604 window.parent.location.href = communityUrl; 605} 606 607function handleGetNotifiedAction(webinar, isLoggedIn) { 608 if (!isLoggedIn) { 609 const loginModal = document.getElementById('loginFormHtml'); 610 if (loginModal) { 611 loginModal.classList.add('active'); 612 } else { 613 window.location.href = '/t/public/login?returnurl=' + encodeURIComponent(window.location.pathname); 614 } 615 } else { 616 if (typeof showAlert === 'function') { 617 showAlert('blue', 'You will be notified about future webinars.'); 618 } else { 619 alert('You will be notified about future webinars.'); 620 } 621 } 622} 623 624async function handleJoinWebinarAction(webinar) { 625 const authToken = localStorage.getItem("microserviceAuthToken"); 626 const isSafari = 627 navigator.vendor && 628 navigator.vendor.indexOf('Apple') > -1 && 629 navigator.userAgent && 630 navigator.userAgent.indexOf('CriOS') == -1 && 631 navigator.userAgent.indexOf('FxiOS') == -1; 632 if (isSafari) { 633 alert('Please disable Block Pop-ups in Settings'); 634 } 635 636 const webinarCurrentState = webinarUtils.getWebinarCurrentState(webinar); 637 try { 638 let webinarId = webinar.id; 639 if (webinarId) { 640 const response = await fetch(`/t/api/content/livesession/${webinarId}/join`, { 641 method: 'GET', 642 headers: { 643 'Authorization': authToken 644 } 645 }) 646 const registrationResponse = await response.json(); 647 const url = registrationResponse.url; 648 if (url) { 649 window.parent.open(url, '_blank'); 650 } else if ('startTime' in webinar) { 651 if ( 652 +new Date(webinar.startTime) < +Date.now() && 653 webinarCurrentState !== 'LIVE' 654 ) { 655 alert('You will be able to join the webinar, once it is started.'); 656 } 657 } 658 } 659 } catch (e) { 660 alert(e?.message || 'Something went wrong'); 661 } 662} 663 664async function handleWatchRecordingAction(webinar) { 665 const authToken = localStorage.getItem("microserviceAuthToken"); 666 try { 667 const response = await fetch('/t/api/user/session/get', { 668 headers: { Authorization: authToken } 669 }); 670 const data = await response.json(); 671 const roles = data?.roles; 672 const isAffiliate = roles?.includes('affiliate'); 673 const isStudent = roles?.includes('student'); 674 675 if (isAffiliate || isStudent) { 676 window.parent.location.href = `/t/u/live-sessions/past?recordingId=${webinar.id}`; 677 } else { 678 window.parent.location.href = `/t/asset-library?liveSessionId=${webinar.id}`; 679 } 680 } catch (error) {} 681}
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.