🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
119 lines
4.7 KiB
TypeScript
119 lines
4.7 KiB
TypeScript
import { Component, Input } from '@angular/core';
|
|
import { CommonModule } from '@angular/common';
|
|
import { ButtonComponent, ContainerComponent } from 'ui-essentials';
|
|
import { CTASectionConfig } from '../../interfaces/conversion.interfaces';
|
|
|
|
@Component({
|
|
selector: 'ui-cta-section',
|
|
standalone: true,
|
|
imports: [
|
|
CommonModule,
|
|
ButtonComponent,
|
|
ContainerComponent,
|
|
],
|
|
template: `
|
|
<section
|
|
class="cta-section"
|
|
[class.cta-section--gradient]="config.backgroundType === 'gradient'"
|
|
[class.cta-section--pattern]="config.backgroundType === 'pattern'"
|
|
[class.cta-section--image]="config.backgroundType === 'image'"
|
|
[class.cta-section--solid]="config.backgroundType === 'solid'">
|
|
|
|
<ui-container>
|
|
<div class="cta-section__content">
|
|
|
|
<!-- Urgency Indicator -->
|
|
<div
|
|
*ngIf="config.urgency"
|
|
class="cta-section__urgency"
|
|
[class.cta-section__urgency--countdown]="config.urgency.type === 'countdown'"
|
|
[class.cta-section__urgency--limited]="config.urgency.type === 'limited-offer'"
|
|
[class.cta-section__urgency--social]="config.urgency.type === 'social-proof'">
|
|
|
|
<div *ngIf="config.urgency.type === 'countdown' && config.urgency.endDate" class="countdown">
|
|
<div class="countdown__item">
|
|
<span class="countdown__value">{{ getTimeRemaining().days }}</span>
|
|
<span class="countdown__label">Days</span>
|
|
</div>
|
|
<div class="countdown__item">
|
|
<span class="countdown__value">{{ getTimeRemaining().hours }}</span>
|
|
<span class="countdown__label">Hours</span>
|
|
</div>
|
|
<div class="countdown__item">
|
|
<span class="countdown__value">{{ getTimeRemaining().minutes }}</span>
|
|
<span class="countdown__label">Minutes</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div *ngIf="config.urgency.type === 'limited-offer'" class="limited-offer">
|
|
<span class="limited-offer__text">{{ config.urgency.text }}</span>
|
|
<span *ngIf="config.urgency.remaining" class="limited-offer__remaining">
|
|
Only {{ config.urgency.remaining }} left!
|
|
</span>
|
|
</div>
|
|
|
|
<div *ngIf="config.urgency.type === 'social-proof'" class="social-proof">
|
|
<span class="social-proof__text">{{ config.urgency.text }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Main Content -->
|
|
<h2 class="cta-section__title">{{ config.title }}</h2>
|
|
|
|
<p *ngIf="config.description" class="cta-section__description">
|
|
{{ config.description }}
|
|
</p>
|
|
|
|
<!-- CTA Buttons -->
|
|
<div class="cta-section__actions">
|
|
<ui-button
|
|
[variant]="config.ctaPrimary.variant || 'filled'"
|
|
[size]="config.ctaPrimary.size || 'large'"
|
|
[disabled]="config.ctaPrimary.disabled || false"
|
|
[loading]="config.ctaPrimary.loading || false"
|
|
(click)="config.ctaPrimary.action()"
|
|
class="cta-section__button cta-section__button--primary">
|
|
{{ config.ctaPrimary.text }}
|
|
</ui-button>
|
|
|
|
<ui-button
|
|
*ngIf="config.ctaSecondary"
|
|
[variant]="config.ctaSecondary.variant || 'outlined'"
|
|
[size]="config.ctaSecondary.size || 'large'"
|
|
[disabled]="config.ctaSecondary.disabled || false"
|
|
[loading]="config.ctaSecondary.loading || false"
|
|
(click)="config.ctaSecondary.action()"
|
|
class="cta-section__button cta-section__button--secondary">
|
|
{{ config.ctaSecondary.text }}
|
|
</ui-button>
|
|
</div>
|
|
</div>
|
|
</ui-container>
|
|
</section>
|
|
`,
|
|
styleUrls: ['./cta-section.component.scss']
|
|
})
|
|
export class CTASectionComponent {
|
|
@Input() config!: CTASectionConfig;
|
|
|
|
getTimeRemaining(): { days: number; hours: number; minutes: number; seconds: number } {
|
|
if (!this.config.urgency?.endDate) {
|
|
return { days: 0, hours: 0, minutes: 0, seconds: 0 };
|
|
}
|
|
|
|
const now = new Date().getTime();
|
|
const end = this.config.urgency.endDate.getTime();
|
|
const difference = end - now;
|
|
|
|
if (difference > 0) {
|
|
return {
|
|
days: Math.floor(difference / (1000 * 60 * 60 * 24)),
|
|
hours: Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
|
|
minutes: Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60)),
|
|
seconds: Math.floor((difference % (1000 * 60)) / 1000)
|
|
};
|
|
}
|
|
|
|
return { days: 0, hours: 0, minutes: 0, seconds: 0 };
|
|
}
|
|
} |