94 lines
2.6 KiB
TypeScript
94 lines
2.6 KiB
TypeScript
import { CommonModule } from '@angular/common';
|
|
import { Component, Input, OnInit } from '@angular/core';
|
|
import { SeoService } from '../../services/seo.service';
|
|
|
|
export interface FAQItem {
|
|
question: string;
|
|
answer: string;
|
|
}
|
|
|
|
@Component({
|
|
selector: 'app-faq',
|
|
standalone: true,
|
|
imports: [CommonModule],
|
|
template: `
|
|
<section class="bg-white rounded-lg shadow-lg p-6 md:p-8 my-8">
|
|
<h2 class="text-2xl md:text-3xl font-bold text-gray-900 mb-6">Frequently Asked Questions</h2>
|
|
|
|
<div class="space-y-4">
|
|
@for (item of faqItems; track $index) {
|
|
<div class="border-b border-gray-200 pb-4">
|
|
<button
|
|
(click)="toggle($index)"
|
|
class="w-full text-left flex justify-between items-center py-2 hover:text-blue-600 transition-colors"
|
|
[attr.aria-expanded]="openIndex === $index"
|
|
>
|
|
<h3 class="text-lg font-semibold text-gray-800">{{ item.question }}</h3>
|
|
<svg
|
|
class="w-5 h-5 transition-transform"
|
|
[class.rotate-180]="openIndex === $index"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
|
</svg>
|
|
</button>
|
|
|
|
@if (openIndex === $index) {
|
|
<div class="mt-3 text-gray-600 leading-relaxed">
|
|
<p [innerHTML]="item.answer"></p>
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
</section>
|
|
`,
|
|
styles: [`
|
|
.rotate-180 {
|
|
transform: rotate(180deg);
|
|
}
|
|
`]
|
|
})
|
|
export class FaqComponent implements OnInit {
|
|
@Input() faqItems: FAQItem[] = [];
|
|
openIndex: number | null = null;
|
|
|
|
constructor(private seoService: SeoService) {}
|
|
|
|
ngOnInit() {
|
|
// Generate and inject FAQ Schema for rich snippets
|
|
if (this.faqItems.length > 0) {
|
|
const faqSchema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'FAQPage',
|
|
'mainEntity': this.faqItems.map(item => ({
|
|
'@type': 'Question',
|
|
'name': item.question,
|
|
'acceptedAnswer': {
|
|
'@type': 'Answer',
|
|
'text': this.stripHtml(item.answer)
|
|
}
|
|
}))
|
|
};
|
|
|
|
this.seoService.injectStructuredData(faqSchema);
|
|
}
|
|
}
|
|
|
|
toggle(index: number) {
|
|
this.openIndex = this.openIndex === index ? null : index;
|
|
}
|
|
|
|
private stripHtml(html: string): string {
|
|
const tmp = document.createElement('DIV');
|
|
tmp.innerHTML = html;
|
|
return tmp.textContent || tmp.innerText || '';
|
|
}
|
|
|
|
ngOnDestroy() {
|
|
this.seoService.clearStructuredData();
|
|
}
|
|
}
|