feat: Initialize BizMatch application with core UI components, routing, listing pages, backend services, migration scripts, and vulnerability management.

This commit is contained in:
Timo
2026-01-03 23:05:38 +01:00
parent e32e43d17f
commit e3e726d8ca
42 changed files with 1478 additions and 1579 deletions

View File

@@ -1,4 +1,5 @@
import { ChangeDetectorRef, Component } from '@angular/core';
import { NgOptimizedImage } from '@angular/common';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { LeafletModule } from '@bluehalo/ngx-leaflet';
@@ -33,7 +34,7 @@ import { ShareButton } from 'ngx-sharebuttons/button';
@Component({
selector: 'app-details-business-listing',
standalone: true,
imports: [SharedModule, ValidatedInputComponent, ValidatedTextareaComponent, ValidatedNgSelectComponent, LeafletModule, BreadcrumbsComponent, ShareButton],
imports: [SharedModule, ValidatedInputComponent, ValidatedTextareaComponent, ValidatedNgSelectComponent, LeafletModule, BreadcrumbsComponent, ShareButton, NgOptimizedImage],
providers: [],
templateUrl: './details-business-listing.component.html',
styleUrl: '../details.scss',
@@ -70,6 +71,7 @@ export class DetailsBusinessListingComponent extends BaseDetailsComponent {
env = environment;
breadcrumbs: BreadcrumbItem[] = [];
relatedListings: BusinessListing[] = [];
businessFAQs: Array<{ question: string; answer: string }> = [];
constructor(
private activatedRoute: ActivatedRoute,
@@ -155,7 +157,13 @@ export class DetailsBusinessListingComponent extends BaseDetailsComponent {
{ name: 'Business Listings', url: '/businessListings' },
{ name: this.selectOptions.getBusiness(this.listing.type), url: `/business/${this.listing.slug || this.listing.id}` }
]);
this.seoService.injectMultipleSchemas([productSchema, breadcrumbSchema]);
// Generate FAQ for AEO (Answer Engine Optimization)
this.businessFAQs = this.generateBusinessFAQ();
const faqSchema = this.seoService.generateFAQPageSchema(this.businessFAQs);
// Inject all schemas including FAQ
this.seoService.injectMultipleSchemas([productSchema, breadcrumbSchema, faqSchema]);
// Generate breadcrumbs
this.breadcrumbs = [
@@ -193,6 +201,101 @@ export class DetailsBusinessListingComponent extends BaseDetailsComponent {
}
}
/**
* Generate dynamic FAQ based on business listing data fields
* Provides AEO (Answer Engine Optimization) content
*/
private generateBusinessFAQ(): Array<{ question: string; answer: string }> {
const faqs: Array<{ question: string; answer: string }> = [];
// FAQ 1: When was this business established?
if (this.listing.established) {
faqs.push({
question: 'When was this business established?',
answer: `This business was established ${this.listing.established} years ago${this.listing.established >= 10 ? ', demonstrating a proven track record and market stability' : ''}.`
});
}
// FAQ 2: What is the asking price?
if (this.listing.price) {
faqs.push({
question: 'What is the asking price for this business?',
answer: `The asking price for this business is $${this.listing.price.toLocaleString()}.${this.listing.salesRevenue ? ` With an annual revenue of $${this.listing.salesRevenue.toLocaleString()}, this represents a competitive valuation.` : ''}`
});
} else {
faqs.push({
question: 'What is the asking price for this business?',
answer: 'The asking price is available upon request. Please contact the seller for detailed pricing information.'
});
}
// FAQ 3: What is included in the sale?
const includedItems: string[] = [];
if (this.listing.realEstateIncluded) includedItems.push('real estate property');
if (this.listing.ffe) includedItems.push(`furniture, fixtures, and equipment valued at $${this.listing.ffe.toLocaleString()}`);
if (this.listing.inventory) includedItems.push(`inventory worth $${this.listing.inventory.toLocaleString()}`);
if (includedItems.length > 0) {
faqs.push({
question: 'What is included in the sale?',
answer: `The sale includes: ${includedItems.join(', ')}.${this.listing.leasedLocation ? ' The business operates from a leased location.' : ''}${this.listing.franchiseResale ? ' This is a franchise resale opportunity.' : ''}`
});
}
// FAQ 4: How many employees does the business have?
if (this.listing.employees) {
faqs.push({
question: 'How many employees does this business have?',
answer: `The business currently employs ${this.listing.employees} ${this.listing.employees === 1 ? 'person' : 'people'}.${this.listing.supportAndTraining ? ' The seller offers support and training to ensure smooth transition.' : ''}`
});
}
// FAQ 5: What is the annual revenue and cash flow?
if (this.listing.salesRevenue || this.listing.cashFlow) {
let answer = '';
if (this.listing.salesRevenue) {
answer += `The business generates an annual revenue of $${this.listing.salesRevenue.toLocaleString()}.`;
}
if (this.listing.cashFlow) {
answer += ` The annual cash flow is $${this.listing.cashFlow.toLocaleString()}.`;
}
faqs.push({
question: 'What is the financial performance of this business?',
answer: answer.trim()
});
}
// FAQ 6: Why is the business for sale?
if (this.listing.reasonForSale) {
faqs.push({
question: 'Why is this business for sale?',
answer: this.listing.reasonForSale
});
}
// FAQ 7: Where is the business located?
faqs.push({
question: 'Where is this business located?',
answer: `This ${this.selectOptions.getBusiness(this.listing.type)} business is located in ${this.listing.location.name || this.listing.location.county}, ${this.selectOptions.getState(this.listing.location.state)}.`
});
// FAQ 8: Is broker licensing required?
if (this.listing.brokerLicencing) {
faqs.push({
question: 'Is a broker license required for this business?',
answer: this.listing.brokerLicencing
});
}
// FAQ 9: What type of business is this?
faqs.push({
question: 'What type of business is this?',
answer: `This is a ${this.selectOptions.getBusiness(this.listing.type)} business${this.listing.established ? ` that has been operating for ${this.listing.established} years` : ''}.`
});
return faqs;
}
ngOnDestroy() {
this.validationMessagesService.clearMessages(); // Löschen Sie alle bestehenden Validierungsnachrichten
this.seoService.clearStructuredData(); // Clean up SEO structured data