202 lines
12 KiB
HTML
202 lines
12 KiB
HTML
<header class="w-full flex justify-between items-center p-4 bg-white fixed top-0 z-10 h-16 md:h-20">
|
|
<img src="assets/images/header-logo.png" alt="Logo" class="h-8 md:h-10" />
|
|
<div class="hidden md:flex items-center space-x-4">
|
|
@if(user){
|
|
<a routerLink="/account" class="text-blue-600 border border-blue-600 px-3 py-2 rounded">Account</a>
|
|
} @else {
|
|
<!-- <a routerLink="/pricing" class="text-gray-800">Pricing</a> -->
|
|
<a (click)="login()" class="text-blue-600 border border-blue-600 px-3 py-2 rounded">Log In</a>
|
|
<a routerLink="/pricing" class="text-white bg-blue-600 px-4 py-2 rounded">Register</a>
|
|
}
|
|
</div>
|
|
<button (click)="toggleMenu()" class="md:hidden text-gray-600">
|
|
<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-gray-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>
|
|
<a href="#" class="text-white text-xl py-2">Log In</a>
|
|
<a href="#" class="text-white text-xl py-2">Register</a>
|
|
<button (click)="toggleMenu()" class="text-white mt-4">
|
|
<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>
|
|
|
|
<main class="flex flex-col items-center justify-center mt-16 md:mt-20 lg:px-4 w-full flex-grow">
|
|
<div class="bg-cover-custom py-20 md:py-40 flex flex-col w-full">
|
|
<div class="flex justify-center w-full">
|
|
<div class="w-11/12 md:w-2/3 lg:w-1/2">
|
|
<h1 class="text-3xl md:text-4xl lg:text-5xl font-bold text-blue-900 mb-4 text-center">Find businesses for sale.</h1>
|
|
<p class="text-base md:text-lg lg:text-xl text-blue-600 mb-8 text-center">Unlocking Exclusive Opportunities - Empowering Entrepreneurial Dreams</p>
|
|
<div class="bg-white bg-opacity-80 p-2 rounded-lg shadow-lg w-full" [ngClass]="{ 'pt-6': aiSearch }">
|
|
@if(!aiSearch){
|
|
<div class="text-sm lg:text-base mb-1 text-center text-gray-500 border-gray-200 dark:text-gray-400 dark:border-gray-700 flex justify-center">
|
|
<ul class="flex flex-wrap -mb-px">
|
|
<li class="me-2">
|
|
<a
|
|
(click)="changeTab('business')"
|
|
[ngClass]="
|
|
activeTabAction === 'business'
|
|
? ['text-blue-600', 'border-blue-600', 'active', 'dark:text-blue-500', 'dark:border-blue-500']
|
|
: ['border-transparent', 'hover:text-gray-600', 'hover:border-gray-300', 'dark:hover:text-gray-300']
|
|
"
|
|
class="hover:cursor-pointer inline-block p-4 border-b-2 rounded-t-lg"
|
|
>Businesses</a
|
|
>
|
|
</li>
|
|
<li class="me-2">
|
|
<a
|
|
(click)="changeTab('commercialProperty')"
|
|
[ngClass]="
|
|
activeTabAction === 'commercialProperty'
|
|
? ['text-blue-600', 'border-blue-600', 'active', 'dark:text-blue-500', 'dark:border-blue-500']
|
|
: ['border-transparent', 'hover:text-gray-600', 'hover:border-gray-300', 'dark:hover:text-gray-300']
|
|
"
|
|
class="hover:cursor-pointer inline-block p-4 border-b-2 rounded-t-lg"
|
|
>Properties</a
|
|
>
|
|
</li>
|
|
<li class="me-2">
|
|
<a
|
|
(click)="changeTab('broker')"
|
|
[ngClass]="
|
|
activeTabAction === 'broker'
|
|
? ['text-blue-600', 'border-blue-600', 'active', 'dark:text-blue-500', 'dark:border-blue-500']
|
|
: ['border-transparent', 'hover:text-gray-600', 'hover:border-gray-300', 'dark:hover:text-gray-300']
|
|
"
|
|
class="hover:cursor-pointer inline-block p-4 border-b-2 rounded-t-lg"
|
|
>Professionals</a
|
|
>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
} @if(aiSearch){
|
|
<div class="w-full max-w-3xl mx-auto bg-white rounded-lg flex flex-col md:flex-row md:border md:border-gray-300">
|
|
<div class="md:w-48 flex-1 md:border-r border-gray-300 overflow-hidden mb-2 md:mb-0">
|
|
<div class="relative max-sm:border border-gray-300 rounded-md">
|
|
<input #aiSearchInput type="text" [(ngModel)]="aiSearchText" name="aiSearchText" class="w-full p-2 border border-gray-300 rounded-md" (focus)="stopTypingEffect()" (blur)="startTypingEffect()" />
|
|
</div>
|
|
</div>
|
|
<div class="bg-blue-600 hover:bg-blue-500 transition-colors duration-200 max-sm:rounded-md">
|
|
<button
|
|
type="button"
|
|
class="w-full h-full text-white font-semibold py-3 px-6 focus:outline-none rounded-md md:rounded-none flex items-center justify-center min-w-[180px] min-h-[48px]"
|
|
(click)="generateAiResponse()"
|
|
>
|
|
<span class="flex items-center">
|
|
@if(loadingAi){
|
|
<svg aria-hidden="true" role="status" class="w-4 h-4 mr-3 text-white animate-spin" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path
|
|
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
|
fill="#E5E7EB"
|
|
/>
|
|
<path
|
|
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
|
fill="currentColor"
|
|
/>
|
|
</svg>
|
|
<span>Loading ...</span>
|
|
} @else {
|
|
<span>Search</span>
|
|
}
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
@if(aiSearchFailed){
|
|
<div id="error-message" class="w-full max-w-3xl mx-auto mt-2 text-red-600 text-center">Search timed out. Please try again or use classic Search</div>
|
|
} } @if(criteria && !aiSearch){
|
|
<div class="w-full max-w-3xl mx-auto bg-white rounded-lg flex flex-col md:flex-row md:border md:border-gray-300">
|
|
<div class="md:flex-none md:w-48 flex-1 md:border-r border-gray-300 overflow-hidden mb-2 md:mb-0">
|
|
<div class="relative max-sm:border border-gray-300 rounded-md">
|
|
<select
|
|
class="appearance-none bg-transparent w-full py-3 px-4 pr-8 focus:outline-none md:border-none rounded-md md:rounded-none"
|
|
[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-gray-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-gray-300 mb-2 md:mb-0">
|
|
<div class="relative max-sm:border border-gray-300 rounded-md">
|
|
<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"
|
|
>
|
|
@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-gray-300 mb-2 md:mb-0">
|
|
<div class="relative max-sm:border border-gray-300 rounded-md">
|
|
<select
|
|
class="appearance-none bg-transparent w-full py-3 px-4 pr-8 focus:outline-none md:border-none rounded-md md:rounded-none"
|
|
(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-gray-700">
|
|
<i class="fas fa-chevron-down text-xs"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
<div class="bg-blue-600 hover:bg-blue-500 transition-colors duration-200 max-sm:rounded-md">
|
|
@if(getNumberOfFiltersSet()>0 && numberOfResults$){
|
|
<button class="w-full h-full text-white font-semibold py-3 px-6 focus:outline-none rounded-md md:rounded-none" (click)="search()">Search ({{ numberOfResults$ | async }})</button>
|
|
}@else {
|
|
<button class="w-full h-full text-white font-semibold py-3 px-6 focus:outline-none rounded-md md:rounded-none" (click)="search()">Search</button>
|
|
}
|
|
</div>
|
|
</div>
|
|
}
|
|
<div class="mt-4 flex items-center justify-center text-gray-700">
|
|
<span class="mr-2">AI-Search</span>
|
|
<span [attr.data-tooltip-target]="tooltipTargetBeta" class="bg-sky-300 text-teal-800 text-xs font-semibold px-2 py-1 rounded">BETA</span>
|
|
<app-tooltip [id]="tooltipTargetBeta" text="The AI will convert your input into filter criteria. Please check them in the filter menu after the search"></app-tooltip>
|
|
<span class="ml-2">- Try now</span>
|
|
<div class="ml-4 relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in">
|
|
<input (click)="toggleAiSearch()" type="checkbox" name="toggle" id="toggle" class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 border-gray-300 appearance-none cursor-pointer" />
|
|
<label for="toggle" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|