Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | 1x 1x 1x 1x 1x 1x 1x 16x 16x 16x 16x 16x 16x 16x 10x 9x 9x 3x 2x 9x 8x 7x 7x 7x 7x 1x 1x 1x 1x 9x 8x 7x 7x 6x 6x 1x 6x 6x 7x 7x 10x 7x 7x 7x 7x 45x 31x 14x 13x 13x 7x 7x 38x 1x 2x 1x | import { Component, OnInit, AfterViewInit, ViewChild, signal, inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { NgFor } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { ApiService, SliderApiResponse, SliderPost, OfferTextApiResponse, OfferTextPost } from '../common/services/api.service';
import { NgbCarousel, NgbSlide } from '@ng-bootstrap/ng-bootstrap';
import { MatIcon } from '@angular/material/icon';
export interface HeroBanner {
id?: number;
title: string;
subtitle: string;
badges: string[];
checklist: string[];
ctaLabel: string;
secondaryCtaLabel: string;
heroImage: string;
heroImage2: string; // New field
label1: string; // New field
label2: string; // New field
link: string;
}
export interface OfferBanner {
title: string;
description: string;
ctaLabel: string;
link: string;
}
@Component({
selector: 'app-m-banner',
standalone: true,
templateUrl: './carousel-banner.component.html',
styleUrls: ['./carousel-banner.component.css'],
imports: [
NgbCarousel,
NgbSlide,
MatIcon,
NgFor,
],
})
export class CarouselBannerComponent implements OnInit {
private readonly apiService = inject(ApiService);
private readonly platformId = inject(PLATFORM_ID);
readonly isBrowser = isPlatformBrowser(this.platformId);
@ViewChild('carousel') private carousel?: NgbCarousel;
// Loading state
readonly isLoading = signal<boolean>(true);
readonly hasError = signal<boolean>(false);
// Component-level state (defaults kept empty — data comes from API)
readonly banners = signal<HeroBanner[]>([]);
readonly offerBanner = signal<OfferBanner | null>(null);
ngOnInit(): void {
if (this.isBrowser) {
this.loadSliderData();
this.loadOfferTextData();
}
}
// Called when a slide change occurs (e.g. user clicked next/prev)
onSlide(event: any): void {
if (!this.isBrowser) return;
// ensure carousel restarts auto-cycling after manual navigation
setTimeout(() => this.carousel?.cycle(), 100);
}
private loadSliderData(): void {
this.apiService.getSlider().subscribe({
next: (response: SliderApiResponse[]) => {
if (response && response.length > 0) {
const sliderData = response[0];
const mappedBanners = this.mapSliderPostsToBanners(sliderData.posts);
this.banners.set(mappedBanners);
this.isLoading.set(false);
} else {
this.isLoading.set(false);
}
},
error: (err) => {
console.error('Slider API Error:', err);
this.hasError.set(true);
this.isLoading.set(false);
}
});
}
private loadOfferTextData(): void {
this.apiService.getOfferText().subscribe({
next: (response: OfferTextApiResponse[]) => {
if (response && response.length > 0) {
const offerData = response[0];
if (offerData.posts && offerData.posts.length > 0) {
const mappedOffer = this.mapOfferTextPostToBanner(offerData.posts[0]);
this.offerBanner.set(mappedOffer);
}
}
},
error: (err) => {
console.error('Offer Text API Error:', err);
}
});
}
private mapOfferTextPostToBanner(post: OfferTextPost): OfferBanner {
const description = this.getWpText(post.description);
return {
title: this.getWpText(post.title, 'PNB Offers'),
description: description,
ctaLabel: post.card_data?.button_label || 'Explore Offers',
link: post.card_data?.button_url || 'https://www.rupay.co.in/domestic-offers'
};
}
private mapSliderPostsToBanners(posts: SliderPost[]): HeroBanner[] {
return posts.map(post => {
const checklist = this.getWpText(post.card_features)
? this.getWpText(post.card_features).split(',').map(feature => feature.trim())
: [];
const subtitle = this.getWpText(post.description);
const excerpt = this.getWpText(post.excerpt);
const badges = excerpt ? [excerpt] : [];
return {
id: post.id,
title: this.getWpText(post.title, 'PNB Credit Card'),
subtitle: subtitle,
badges: badges,
checklist: checklist,
ctaLabel: post.card_data?.button_label || 'Apply Now',
secondaryCtaLabel: post.card_data?.button_label || 'Learn More',
heroImage: post.featured_image || 'assets/images/banner1.webp',
heroImage2: post.featured_image2 || '', // Mapped from featured_image2
label1: post.banner_label1_text_box || '', // Mapped from banner_label1_text_box
label2: post.banner_label2_text_box || '', // Mapped from banner_label2_text_box
link: post.card_data?.button_url || 'https://www.rupay.co.in/domestic-offers'
};
});
}
private getWpText(value: unknown, fallback = ''): string {
if (typeof value === 'string') {
return this.cleanText(value);
}
if (value && typeof value === 'object' && 'rendered' in value) {
const rendered = (value as { rendered?: unknown }).rendered;
if (typeof rendered === 'string') {
return this.cleanText(rendered);
}
}
return fallback;
}
private cleanText(value: string): string {
return value.replace(/<[^>]*>/g, '').trim();
}
openApplyPagebanner(): void {
window.open('https://apply.creditcard.pnb.bank.in/', '_blank');
}
openApplyPage(url: string): void {
if (!url) return;
window.open(url, '_blank', 'noopener,noreferrer');
}
}
|