Files
bizmatch-project/bizmatch/src/app/pages/home/home.component.html

264 lines
15 KiB
HTML

<header class="w-full flex justify-between items-center p-4 bg-white top-0 z-10 h-16 md:h-20">
<img src="/assets/images/header-logo.png" alt="BizMatch - Business & Property Marketplace" class="h-8 md:h-10 w-auto" width="120" height="40" />
<div class="hidden md:flex items-center space-x-4">
@if(user){
<a routerLink="/account" class="text-primary-600 border border-primary-600 px-3 py-2 rounded">Account</a>
} @else {
<!-- <a routerLink="/pricing" class="text-neutral-800">Pricing</a> -->
<a routerLink="/login" [queryParams]="{ mode: 'login' }" class="text-primary-600 border border-primary-600 px-3 py-2 rounded">Log In</a>
<a routerLink="/login" [queryParams]="{ mode: 'register' }" class="text-white bg-primary-600 px-4 py-2 rounded">Sign Up</a>
<!-- <a routerLink="/login" class="text-primary-500 hover:underline">Login/Register</a> -->
}
</div>
<button
(click)="toggleMenu()"
class="md:hidden text-neutral-700 p-2 min-w-[44px] min-h-[44px] flex items-center justify-center"
aria-label="Open navigation menu"
[attr.aria-expanded]="isMenuOpen"
>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16m-7 6h7"></path>
</svg>
</button>
</header>
<div *ngIf="isMenuOpen" class="fixed inset-0 bg-neutral-800 bg-opacity-75 z-20">
<div class="flex flex-col items-center justify-center h-full">
<!-- <a href="#" class="text-white text-xl py-2">Pricing</a> -->
@if(user){
<a routerLink="/account" class="text-white text-xl py-2">Account</a>
} @else {
<a routerLink="/login" [queryParams]="{ mode: 'login' }" class="text-white text-xl py-2">Log In</a>
<a routerLink="/login" [queryParams]="{ mode: 'register' }" class="text-white text-xl py-2">Sign Up</a>
}
<button
(click)="toggleMenu()"
class="text-white mt-4"
aria-label="Close navigation menu"
>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
</div>
<!-- ==== ANPASSUNGEN START ==== -->
<!-- 1. px-4 für <main> (vorher px-2 sm:px-4) -->
<main class="flex flex-col items-center justify-center px-4 w-full flex-grow">
<div
class="relative overflow-hidden pb-12 md:py-20 flex flex-col w-full rounded-xl lg:rounded-2xl md:drop-shadow-custom-md lg:drop-shadow-custom-lg min-h-[calc(100vh_-_20rem)] lg:min-h-[calc(100vh_-_10rem)] max-sm:min-h-[60vh] max-sm:bg-primary-600"
>
<!-- Optimized Background Image -->
<picture class="absolute inset-0 w-full h-full z-0 pointer-events-none">
<source srcset="/assets/images/flags_bg.avif" type="image/avif">
<img
width="2500"
height="1285"
fetchpriority="high"
loading="eager"
src="/assets/images/flags_bg.jpg"
alt=""
class="w-full h-full object-cover"
>
</picture>
<!-- Gradient Overlay -->
<div class="absolute inset-0 bg-gradient-to-b from-black/35 via-black/15 to-transparent z-0 pointer-events-none"></div>
<div class="flex justify-center w-full relative z-10">
<!-- 3. Für Mobile: m-2 statt max-w-xs; ab sm: wieder max-width und kein Margin -->
<div class="w-full m-2 sm:m-0 sm:max-w-md md:max-w-xl lg:max-w-2xl xl:max-w-3xl">
<!-- Hero-Container -->
<section class="relative">
<!-- Dein Hintergrundbild liegt hier per CSS oder absolutem <img> -->
<!-- 1) Overlay: sorgt für Kontrast auf hellem Himmel (Previous overlay removed, using new global overlay) -->
<!-- <div aria-hidden="true" class="pointer-events-none absolute inset-0"></div> -->
<!-- 2) Textblock -->
<div class="relative z-10 mx-auto max-w-4xl px-6 sm:px-6 py-4 sm:py-16 text-center text-white">
<h1 class="text-[1.55rem] sm:text-4xl md:text-5xl lg:text-6xl font-extrabold tracking-tight leading-tight drop-shadow-[0_2px_6px_rgba(0,0,0,0.55)]">Buy & Sell Businesses and Commercial Properties</h1>
<p class="mt-3 sm:mt-4 text-base sm:text-lg md:text-xl lg:text-2xl font-medium text-white/90 drop-shadow-[0_1.5px_4px_rgba(0,0,0,0.6)]">
Buy profitable businesses for sale or sell your business to qualified buyers. Browse commercial real estate and franchise opportunities across the United States.
</p>
</div>
</section>
<!-- Restliche Anpassungen (Innenabstände, Button-Paddings etc.) bleiben wie im vorherigen Schritt -->
<div class="search-form-container bg-white bg-opacity-80 pb-4 md:pb-6 pt-2 px-3 sm:px-4 md:px-6 rounded-lg shadow-lg w-full" [ngClass]="{ 'pt-6': aiSearch }">
@if(!aiSearch){
<div class="text-sm lg:text-base mb-1 text-center text-neutral-700 border-neutral-200 dark:text-neutral-300 dark:border-neutral-700 flex justify-between">
<ul class="flex flex-wrap -mb-px w-full" role="tablist" aria-label="Search categories">
<li class="w-[33%]" role="presentation">
<button
type="button"
role="tab"
[attr.aria-selected]="activeTabAction === 'business'"
(click)="changeTab('business')"
[ngClass]="
activeTabAction === 'business'
? ['text-primary-600', 'border-primary-600', 'active', 'dark:text-primary-500', 'dark:border-primary-500']
: ['border-transparent', 'text-neutral-700', 'hover:text-neutral-900', 'hover:border-neutral-400', 'dark:hover:text-neutral-300']
"
class="tab-link w-full hover:cursor-pointer inline-flex items-center justify-center px-3 py-3 md:p-4 border-b-2 rounded-t-lg bg-transparent min-h-[44px]"
[attr.aria-controls]="'tabpanel-search'"
id="tab-business"
>
<img src="/assets/images/business_logo.png" alt="" aria-hidden="true" class="tab-icon w-6 h-6 md:w-7 md:h-7 mr-1 md:mr-2 object-contain" width="28" height="28" />
<span>Businesses</span>
</button>
</li>
@if ((numberOfCommercial$ | async) > 0) {
<li class="w-[33%]" role="presentation">
<button
type="button"
role="tab"
[attr.aria-selected]="activeTabAction === 'commercialProperty'"
(click)="changeTab('commercialProperty')"
[ngClass]="
activeTabAction === 'commercialProperty'
? ['text-primary-600', 'border-primary-600', 'active', 'dark:text-primary-500', 'dark:border-primary-500']
: ['border-transparent', 'text-neutral-700', 'hover:text-neutral-900', 'hover:border-neutral-400', 'dark:hover:text-neutral-300']
"
class="tab-link w-full hover:cursor-pointer inline-flex items-center justify-center px-3 py-3 md:p-4 border-b-2 rounded-t-lg bg-transparent min-h-[44px]"
[attr.aria-controls]="'tabpanel-search'"
id="tab-properties"
>
<img src="/assets/images/properties_logo.png" alt="" aria-hidden="true" class="tab-icon w-6 h-6 md:w-7 md:h-7 mr-1 md:mr-2 object-contain" width="28" height="28" />
<span>Properties</span>
</button>
</li>
}
<li class="w-[33%]" role="presentation">
<button
type="button"
role="tab"
[attr.aria-selected]="activeTabAction === 'broker'"
(click)="changeTab('broker')"
[ngClass]="
activeTabAction === 'broker'
? ['text-primary-600', 'border-primary-600', 'active', 'dark:text-primary-500', 'dark:border-primary-500']
: ['border-transparent', 'text-neutral-700', 'hover:text-neutral-900', 'hover:border-neutral-400', 'dark:hover:text-neutral-300']
"
class="tab-link w-full hover:cursor-pointer inline-flex items-center justify-center px-3 py-3 md:p-4 border-b-2 rounded-t-lg bg-transparent min-h-[44px]"
[attr.aria-controls]="'tabpanel-search'"
id="tab-professionals"
>
<img
src="/assets/images/icon_professionals.png"
alt=""
aria-hidden="true"
class="tab-icon w-6 h-6 md:w-7 md:h-7 mr-1 md:mr-2 object-contain"
style="mix-blend-mode: darken"
width="28" height="28"
/>
<span>Professionals</span>
</button>
</li>
</ul>
</div>
} @if(criteria && !aiSearch){
<div id="tabpanel-search" role="tabpanel" aria-labelledby="tab-business" class="w-full max-w-3xl mx-auto bg-white rounded-lg flex flex-col md:flex-row md:border md:border-neutral-300">
<div class="md:flex-none md:w-48 flex-1 md:border-r border-neutral-300 overflow-hidden mb-2 md:mb-0">
<div class="relative max-sm:border border-neutral-300 rounded-md">
<label for="type-filter" class="sr-only">Filter by type</label>
<select
id="type-filter"
aria-label="Filter by type"
class="appearance-none bg-transparent w-full py-4 px-4 pr-8 focus:outline-none md:border-none rounded-md md:rounded-none min-h-[52px]"
[ngModel]="criteria.types"
(ngModelChange)="onTypesChange($event)"
[ngClass]="{ 'placeholder-selected': criteria.types.length === 0 }"
>
<option [value]="[]">{{ getPlaceholderLabel() }}</option>
@for(type of getTypes(); track type){
<option [value]="type.value">{{ type.name }}</option>
}
</select>
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-neutral-700">
<i class="fas fa-chevron-down text-xs"></i>
</div>
</div>
</div>
<div class="md:flex-auto md:w-36 flex-grow md:border-r border-neutral-300 mb-2 md:mb-0">
<div class="relative max-sm:border border-neutral-300 rounded-md">
<label for="location-search" class="sr-only">Search by city or state</label>
<ng-select
class="custom md:border-none rounded-md md:rounded-none"
[multiple]="false"
[hideSelected]="true"
[trackByFn]="trackByFn"
[minTermLength]="2"
[loading]="cityLoading"
typeToSearchText="Please enter 2 or more characters"
[typeahead]="cityInput$"
[ngModel]="cityOrState"
(ngModelChange)="setCityOrState($event)"
placeholder="Enter City or State ..."
groupBy="type"
labelForId="location-search"
aria-label="Search by city or state"
[inputAttrs]="{'aria-describedby': 'location-search-hint'}"
>
<ng-template ng-footer-tmp>
<span id="location-search-hint" class="sr-only">Enter at least 2 characters to search for a city or state</span>
</ng-template>
@for (city of cities$ | async; track city.id) { @let state = city.type==='city'?city.content.state:''; @let separator = city.type==='city'?' - ':'';
<ng-option [value]="city">{{ city.content.name }}{{ separator }}{{ state }}</ng-option>
}
</ng-select>
</div>
</div>
@if (criteria.radius && !aiSearch){
<div class="md:flex-none md:w-36 flex-1 md:border-r border-neutral-300 mb-2 md:mb-0">
<div class="relative max-sm:border border-neutral-300 rounded-md">
<label for="radius-filter" class="sr-only">Filter by radius</label>
<select
id="radius-filter"
aria-label="Filter by radius"
class="appearance-none bg-transparent w-full py-4 px-4 pr-8 focus:outline-none md:border-none rounded-md md:rounded-none min-h-[52px]"
(ngModelChange)="onRadiusChange($event)"
[ngModel]="criteria.radius"
[ngClass]="{ 'placeholder-selected': !criteria.radius }"
>
<option [value]="null">City Radius</option>
@for(dist of selectOptions.distances; track dist){
<option [value]="dist.value">{{ dist.name }}</option>
}
</select>
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-neutral-700">
<i class="fas fa-chevron-down text-xs"></i>
</div>
</div>
</div>
}
<div class="bg-primary-500 hover:bg-primary-600 max-sm:rounded-md search-button">
@if( numberOfResults$){
<button aria-label="Search listings" class="w-full h-full text-white font-bold py-2 px-4 md:py-3 md:px-6 focus:outline-none rounded-md md:rounded-none min-h-[52px] flex items-center justify-center gap-2" (click)="search()">
<i class="fas fa-search" aria-hidden="true"></i>
<span>Search {{ numberOfResults$ | async }}</span>
</button>
}@else {
<button aria-label="Search listings" class="w-full h-full text-white font-bold py-2 px-4 md:py-3 md:px-6 focus:outline-none rounded-md md:rounded-none min-h-[52px] flex items-center justify-center gap-2" (click)="search()">
<i class="fas fa-search" aria-hidden="true"></i>
<span>Search</span>
</button>
}
</div>
</div>
}
</div>
</div>
</div>
</div>
<!-- FAQ Section for SEO/AEO -->
<!-- <div class="w-full px-4 mt-12 max-w-4xl mx-auto">
<app-faq [faqItems]="faqItems"></app-faq>
</div> -->
</main>
<!-- ==== ANPASSUNGEN ENDE ==== -->