Compare commits
2 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
9235cb0f22 | |
|
|
eb23bebc10 |
|
|
@ -3,7 +3,7 @@
|
|||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve --host 0.0.0.0 & http-server ../bizmatch-server",
|
||||
"start": "ng serve --port=4300 --host 0.0.0.0 & http-server ../bizmatch-server",
|
||||
"prebuild": "node version.js",
|
||||
"build": "node version.js && ng build",
|
||||
"build.dev": "node version.js && ng build --configuration dev --output-hashing=all",
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
"@angular/core": "^18.1.3",
|
||||
"@angular/fire": "^18.0.1",
|
||||
"@angular/forms": "^18.1.3",
|
||||
"@angular/google-maps": "^18.2.14",
|
||||
"@angular/platform-browser": "^18.1.3",
|
||||
"@angular/platform-browser-dynamic": "^18.1.3",
|
||||
"@angular/platform-server": "^18.1.3",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
<main class="flex-1">
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -43,38 +43,11 @@ export class AppComponent {
|
|||
while (currentRoute.children[0] !== undefined) {
|
||||
currentRoute = currentRoute.children[0];
|
||||
}
|
||||
// Hier haben Sie Zugriff auf den aktuellen Route-Pfad
|
||||
this.actualRoute = currentRoute.snapshot.url[0].path;
|
||||
});
|
||||
}
|
||||
ngOnInit() {
|
||||
// this.keycloakService.keycloakEvents$.subscribe({
|
||||
// next: event => {
|
||||
// if (event.type === KeycloakEventType.OnTokenExpired) {
|
||||
// this.handleTokenExpiration();
|
||||
// }
|
||||
// },
|
||||
// });
|
||||
}
|
||||
// private async handleTokenExpiration(): Promise<void> {
|
||||
// try {
|
||||
// // Versuche, den Token zu erneuern
|
||||
// const refreshed = await this.keycloakService.updateToken();
|
||||
// if (!refreshed) {
|
||||
// // Wenn der Token nicht erneuert werden kann, leite zur Login-Seite weiter
|
||||
// this.keycloakService.login({
|
||||
// redirectUri: window.location.href, // oder eine andere Seite
|
||||
// });
|
||||
// }
|
||||
// } catch (error) {
|
||||
// if (error.error === 'invalid_grant' && error.error_description === 'Token is not active') {
|
||||
// // Hier wird der Fehler "invalid_grant" abgefangen
|
||||
// this.keycloakService.login({
|
||||
// redirectUri: window.location.href,
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
ngOnInit() {}
|
||||
|
||||
@HostListener('window:keydown', ['$event'])
|
||||
handleKeyboardEvent(event: KeyboardEvent) {
|
||||
if (event.shiftKey && event.ctrlKey && event.key === 'V') {
|
||||
|
|
|
|||
|
|
@ -28,17 +28,14 @@ export const routes: Routes = [
|
|||
{
|
||||
path: 'businessListings',
|
||||
component: BusinessListingsComponent,
|
||||
runGuardsAndResolvers: 'always',
|
||||
},
|
||||
{
|
||||
path: 'commercialPropertyListings',
|
||||
component: CommercialPropertyListingsComponent,
|
||||
runGuardsAndResolvers: 'always',
|
||||
},
|
||||
{
|
||||
path: 'brokerListings',
|
||||
component: BrokerListingsComponent,
|
||||
runGuardsAndResolvers: 'always',
|
||||
},
|
||||
{
|
||||
path: 'home',
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
<ng-template #otherRoute>
|
||||
<footer class="bg-white px-4 py-2 md:px-6 mt-auto w-full print:hidden">
|
||||
<div class="container mx-auto flex flex-col lg:flex-row justify-between items-center">
|
||||
<div class="flex flex-col lg:flex-row items-center mb-4 lg:mb-0">
|
||||
|
|
@ -27,6 +28,55 @@
|
|||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</ng-template>
|
||||
<footer *ngIf="isHomeRoute; else otherRoute" class="bg-gray-800 text-white pt-12 pb-4">
|
||||
<div class="container mx-auto px-6">
|
||||
<div class="flex flex-wrap">
|
||||
<div class="w-full md:w-1/3 mb-8 md:mb-0">
|
||||
<h3 class="text-xl font-semibold mb-4">BizMatch</h3>
|
||||
<p class="mb-2">Your trusted partner in business brokerage.</p>
|
||||
<p class="mb-2">TREC License #0516 788</p>
|
||||
</div>
|
||||
|
||||
<div class="w-full md:w-1/3 mb-8 md:mb-0">
|
||||
<h3 class="text-xl font-semibold mb-4">Quick Links</h3>
|
||||
<ul>
|
||||
<li class="mb-2">
|
||||
<a href="#" class="text-gray-300 hover:text-white">Home</a>
|
||||
</li>
|
||||
<li class="mb-2">
|
||||
<a href="#services" class="text-gray-300 hover:text-white">Services</a>
|
||||
</li>
|
||||
<li class="mb-2">
|
||||
<a href="#location" class="text-gray-300 hover:text-white">Location</a>
|
||||
</li>
|
||||
<li class="mb-2">
|
||||
<a href="#contact" class="text-gray-300 hover:text-white">Contact</a>
|
||||
</li>
|
||||
<li class="mb-2">
|
||||
<a data-drawer-target="terms-of-use" data-drawer-show="terms-of-use" aria-controls="terms-of-use" class="text-gray-300 hover:text-white">Terms of use</a>
|
||||
</li>
|
||||
<li class="mb-2">
|
||||
<a data-drawer-target="privacy" data-drawer-show="privacy" aria-controls="privacy" class="text-gray-300 hover:text-white">Privacy statement</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="w-full md:w-1/3">
|
||||
<h3 class="text-xl font-semibold mb-4">Contact Us</h3>
|
||||
<p class="mb-2">1001 Blucher Street</p>
|
||||
<p class="mb-2">Corpus Christi, TX 78401</p>
|
||||
<p class="mb-4">United States</p>
|
||||
<p class="mb-2">1-800-840-6025</p>
|
||||
<p class="mb-2">info@bizmatch.net</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-4 text-center">
|
||||
<p class="text-sm text-gray-400 mt-4">© 2025 BizMatch. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<div id="privacy" class="fixed top-0 left-0 z-40 h-screen p-4 overflow-y-auto transition-transform -translate-x-full bg-white lg:w-1/3 w-96 dark:bg-gray-800" tabindex="-1" aria-labelledby="drawer-label">
|
||||
<h5 id="drawer-label" class="inline-flex items-center mb-4 text-base font-semibold text-gray-500 dark:text-gray-400">
|
||||
<svg class="w-4 h-4 me-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
:host {
|
||||
// position: absolute;
|
||||
// bottom: 0px;
|
||||
width: 100%;
|
||||
}
|
||||
div {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
.order-2 {
|
||||
order: 2;
|
||||
|
|
|
|||
|
|
@ -15,10 +15,12 @@ export class FooterComponent {
|
|||
privacyVisible = false;
|
||||
termsVisible = false;
|
||||
currentYear: number = new Date().getFullYear();
|
||||
isHomeRoute = false;
|
||||
constructor(private router: Router) {}
|
||||
ngOnInit() {
|
||||
this.router.events.subscribe(event => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
this.isHomeRoute = event.url === '/home';
|
||||
initFlowbite();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<nav class="bg-white border-gray-200 dark:bg-gray-900 print:hidden">
|
||||
<div class="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4">
|
||||
<div class="flex flex-wrap items-center justify-between mx-auto p-4">
|
||||
<a routerLink="/home" class="flex items-center space-x-3 rtl:space-x-reverse">
|
||||
<img src="assets/images/header-logo.png" class="h-8" alt="Flowbite Logo" />
|
||||
</a>
|
||||
|
|
@ -63,28 +63,19 @@
|
|||
<li>
|
||||
<a routerLink="/account" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Account</a>
|
||||
</li>
|
||||
@if((user.customerType==='professional' && user.customerSubType==='broker') || user.customerType==='seller' || (authService.isAdmin() | async)){
|
||||
@if(isProfessional || (authService.isAdmin() | async) && user?.hasProfile){
|
||||
<li>
|
||||
@if(user.customerType==='professional'){
|
||||
<a routerLink="/createBusinessListing" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
|
||||
>Create Listing</a
|
||||
>
|
||||
}@else {
|
||||
<a routerLink="/createCommercialPropertyListing" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
|
||||
>Create Listing</a
|
||||
>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
<li>
|
||||
<a routerLink="/myListings" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">My Listings</a>
|
||||
</li>
|
||||
}
|
||||
<li>
|
||||
<a routerLink="/myFavorites" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">My Favorites</a>
|
||||
</li>
|
||||
<li>
|
||||
<a routerLink="/emailUs" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">EMail Us</a>
|
||||
</li>
|
||||
<li>
|
||||
<a routerLink="/logout" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Logout</a>
|
||||
</li>
|
||||
|
|
@ -96,7 +87,7 @@
|
|||
</li>
|
||||
</ul>
|
||||
}
|
||||
<ul class="py-2 md:hidden">
|
||||
<!-- <ul class="py-2 md:hidden">
|
||||
<li>
|
||||
<a
|
||||
routerLink="/businessListings"
|
||||
|
|
@ -127,7 +118,7 @@
|
|||
>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</ul> -->
|
||||
</div>
|
||||
} @else {
|
||||
<div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded-lg shadow dark:bg-gray-700 dark:divide-gray-600" id="user-unknown">
|
||||
|
|
@ -135,11 +126,11 @@
|
|||
<li>
|
||||
<a routerLink="/login" [queryParams]="{ mode: 'login' }" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Log In</a>
|
||||
</li>
|
||||
<li>
|
||||
<!-- <li>
|
||||
<a routerLink="/login" [queryParams]="{ mode: 'register' }" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Sign Up</a>
|
||||
</li>
|
||||
</li> -->
|
||||
</ul>
|
||||
<ul class="py-2 md:hidden">
|
||||
<!-- <ul class="py-2 md:hidden">
|
||||
<li>
|
||||
<a
|
||||
routerLink="/businessListings"
|
||||
|
|
@ -170,11 +161,11 @@
|
|||
>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</ul> -->
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1" id="navbar-user">
|
||||
<!-- <div class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1" id="navbar-user">
|
||||
<ul
|
||||
class="flex flex-col font-medium p-4 md:p-0 mt-4 border border-gray-100 rounded-lg bg-gray-50 md:space-x-8 rtl:space-x-reverse md:flex-row md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700"
|
||||
>
|
||||
|
|
@ -213,7 +204,7 @@
|
|||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<!-- Mobile filter button -->
|
||||
<div class="md:hidden flex justify-center pb-4">
|
||||
|
|
|
|||
|
|
@ -135,6 +135,9 @@ export class HeaderComponent {
|
|||
isActive(route: string): boolean {
|
||||
return this.router.url === route;
|
||||
}
|
||||
isEmailUsUrl(): boolean {
|
||||
return ['/emailUs'].includes(this.router.url);
|
||||
}
|
||||
isFilterUrl(): boolean {
|
||||
return ['/businessListings', '/commercialPropertyListings', '/brokerListings'].includes(this.router.url);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ export class LoginRegisterComponent {
|
|||
onSubmit(): void {
|
||||
this.errorMessage = '';
|
||||
if (this.isLoginMode) {
|
||||
this.authService.clearRoleCache();
|
||||
this.authService
|
||||
.loginWithEmail(this.email, this.password)
|
||||
.then(userCredential => {
|
||||
|
|
@ -81,6 +82,7 @@ export class LoginRegisterComponent {
|
|||
// Login with Google
|
||||
loginWithGoogle(): void {
|
||||
this.errorMessage = '';
|
||||
this.authService.clearRoleCache();
|
||||
this.authService
|
||||
.loginWithGoogle()
|
||||
.then(userCredential => {
|
||||
|
|
|
|||
|
|
@ -1,183 +1,252 @@
|
|||
<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="Logo" class="h-8 md:h-10" />
|
||||
<div class="hidden md:flex items-center space-x-4">
|
||||
<!-- Navigation -->
|
||||
<nav class="bg-white">
|
||||
<div class="container mx-auto px-6 py-3 flex justify-between items-center">
|
||||
<div class="flex items-center">
|
||||
<a href="#" class="text-2xl font-bold text-blue-800">
|
||||
<img src="assets/images/header-logo.png" alt="BizMatch.net" class="h-10" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="hidden md:flex items-center space-x-8">
|
||||
<a href="#" class="text-gray-800 hover:text-blue-600">Home</a>
|
||||
<a routerLink="/businessListings" class="text-blue-700 hover:font-bold">Businesses</a>
|
||||
<a href="#services" class="text-gray-800 hover:text-blue-600">Services</a>
|
||||
<a href="#location" class="text-gray-800 hover:text-blue-600">Location</a>
|
||||
<a href="#contact" class="text-gray-800 hover:text-blue-600">Contact</a>
|
||||
@if(user){
|
||||
<a routerLink="/account" class="text-blue-600 border border-blue-600 px-3 py-2 rounded">Account</a>
|
||||
<a routerLink="/logout" class="text-gray-800 hover:text-blue-600">Logout</a>
|
||||
}@else{
|
||||
<!-- <a routerLink="/pricing" class="text-gray-800">Pricing</a> -->
|
||||
<a routerLink="/login" [queryParams]="{ mode: 'login' }" class="text-blue-600 border border-blue-600 px-3 py-2 rounded">Log In</a>
|
||||
<a routerLink="/login" [queryParams]="{ mode: 'register' }" class="text-white bg-blue-600 px-4 py-2 rounded">Register</a>
|
||||
<!-- <a routerLink="/login" class="text-blue-500 hover:underline">Login/Register</a> -->
|
||||
<a routerLink="/login" [queryParams]="{ mode: 'login' }" class="text-gray-800 hover:text-blue-600">Log In</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> -->
|
||||
@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">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>
|
||||
<div class="md:hidden">
|
||||
<button class="text-gray-800 focus:outline-none" (click)="toggleMobileMenu()">
|
||||
<svg class="h-6 w-6 fill-current" viewBox="0 0 24 24">
|
||||
<path d="M4 5h16a1 1 0 0 1 0 2H4a1 1 0 1 1 0-2zm0 6h16a1 1 0 0 1 0 2H4a1 1 0 0 1 0-2zm0 6h16a1 1 0 0 1 0 2H4a1 1 0 0 1 0-2z"></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="bg-cover-custom py-12 md:py-20 lg:py-32 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)]">
|
||||
<div class="flex justify-center w-full">
|
||||
<!-- 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">
|
||||
<!-- Schriftgrößen angepasst (wie vorher) -->
|
||||
<h1 class="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold text-blue-900 mb-3 sm:mb-4 text-center">Find businesses for sale.</h1>
|
||||
<!-- Abstand unten angepasst (wie vorher) -->
|
||||
<p class="text-base md:text-lg lg:text-xl text-blue-600 mb-6 md:mb-8 text-center">Unlocking Exclusive Opportunities - Empowering Entrepreneurial Dreams</p>
|
||||
<!-- Restliche Anpassungen (Innenabstände, Button-Paddings etc.) bleiben wie im vorherigen Schritt -->
|
||||
<div class="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-gray-500 border-gray-200 dark:text-gray-400 dark:border-gray-700 flex justify-between">
|
||||
<ul class="flex flex-wrap -mb-px w-full">
|
||||
<li class="w-[33%]">
|
||||
<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 px-1 py-2 md:p-4 border-b-2 rounded-t-lg"
|
||||
>Businesses</a
|
||||
>
|
||||
</li>
|
||||
@if ((numberOfCommercial$ | async) > 0) {
|
||||
<li class="w-[33%]">
|
||||
<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 px-1 py-2 md:p-4 border-b-2 rounded-t-lg"
|
||||
>Properties</a
|
||||
>
|
||||
</li>
|
||||
} @if ((numberOfBroker$ | async) > 0) {
|
||||
<li class="w-[33%]">
|
||||
<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 px-1 py-2 md:p-4 border-b-2 rounded-t-lg"
|
||||
>Professionals</a
|
||||
>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</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-2 px-4 md:py-3 md:px-6 focus:outline-none rounded-md md:rounded-none min-h-[48px]" (click)="search()">
|
||||
Search ({{ numberOfResults$ | async }})
|
||||
</button>
|
||||
<!-- Mobile menu (only shows when toggleMobileMenu is true) -->
|
||||
<div *ngIf="showMobileMenu" class="md:hidden bg-white py-2 px-4">
|
||||
<a href="#" class="block py-2 text-gray-800 hover:text-blue-600">Home</a>
|
||||
<a href="#services" class="block py-2 text-gray-800 hover:text-blue-600">Services</a>
|
||||
<a href="#location" class="block py-2 text-gray-800 hover:text-blue-600">Location</a>
|
||||
<a href="#contact" class="block py-2 text-gray-800 hover:text-blue-600">Contact</a>
|
||||
@if(user){
|
||||
<a routerLink="/logout" class="block py-2 text-gray-800 hover:text-blue-600">Logout</a>
|
||||
}@else{
|
||||
<button class="w-full h-full text-white font-semibold py-2 px-4 md:py-3 md:px-6 focus:outline-none rounded-md md:rounded-none min-h-[48px]" (click)="search()">Search</button>
|
||||
<a routerLink="/login" [queryParams]="{ mode: 'login' }" class="block py-2 text-gray-800 hover:text-blue-600">Log In</a>
|
||||
}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Hero Section (made narrower) -->
|
||||
<section class="hero-section flex items-center px-[2rem] py-[5rem]">
|
||||
<div class="container mx-auto px-6 flex flex-col">
|
||||
<!-- max-w-5xl makes it narrower -->
|
||||
<div class="flex flex-col md:flex-row items-center">
|
||||
<div class="md:w-1/2 text-white">
|
||||
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold leading-tight mb-4">Connect with Your Ideal Business Opportunity</h1>
|
||||
<p class="text-xl mb-8">BizMatch is your trusted partner in buying, selling, and valuing businesses in Texas.</p>
|
||||
</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="AI will convert your input into filter criteria. Please check them in the filter menu after 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 class="md:w-1/2 flex justify-center">
|
||||
<img src="assets/images/corpusChristiSkyline.jpg" alt="Business handshake" class="rounded-lg shadow-2xl" />
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<div class="flex justify-center mt-10">
|
||||
<a routerLink="/businessListings" class="bg-green-500 md:text-2xl text-lg text-white font-semibold px-8 py-4 rounded-full shadow-lg hover:bg-green-600 transition duration-300"> View Available Businesses </a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Section -->
|
||||
<section id="services" class="py-20 bg-gray-50">
|
||||
<div class="container mx-auto px-6">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-3xl font-bold text-blue-800 mb-4">Our Services</h2>
|
||||
<p class="text-gray-600 max-w-2xl mx-auto">We offer comprehensive business brokerage services to help you navigate the complex process of buying or selling a business.</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap -mx-4">
|
||||
<!-- Service 1 -->
|
||||
<div class="w-full md:w-1/3 px-4 mb-8">
|
||||
<div class="service-card bg-white rounded-lg filter md:drop-shadow-custom-bg drop-shadow-custom-bg-mobile p-8 h-full">
|
||||
<div class="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mb-6 mx-auto">
|
||||
<svg class="w-8 h-8 text-blue-600" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path
|
||||
d="M13 6a3 3 0 11-6 0 3 3 0 016 0zM18 8a2 2 0 11-4 0 2 2 0 014 0zM14 15a4 4 0 00-8 0v3h8v-3zM6 8a2 2 0 11-4 0 2 2 0 014 0zM16 18v-3a5.972 5.972 0 00-.75-2.906A3.005 3.005 0 0119 15v3h-3zM4.75 12.094A5.973 5.973 0 004 15v3H1v-3a3 3 0 013.75-2.906z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-blue-800 mb-4 text-center">Business Sales</h3>
|
||||
<p class="text-gray-600 text-center">We help business owners prepare and market their businesses to qualified buyers, ensuring confidentiality throughout the process.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service 2 -->
|
||||
<div class="w-full md:w-1/3 px-4 mb-8">
|
||||
<div class="service-card bg-white rounded-lg filter md:drop-shadow-custom-bg drop-shadow-custom-bg-mobile p-8 h-full">
|
||||
<div class="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mb-6 mx-auto">
|
||||
<svg class="w-8 h-8 text-blue-600" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M4 4a2 2 0 00-2 2v4a2 2 0 002 2V6h10a2 2 0 00-2-2H4zm2 6a2 2 0 012-2h8a2 2 0 012 2v4a2 2 0 01-2 2H8a2 2 0 01-2-2v-4zm6 4a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-blue-800 mb-4 text-center">Business Acquisitions</h3>
|
||||
<p class="text-gray-600 text-center">We assist buyers in finding the right business opportunity, perform due diligence, and negotiate favorable terms for acquisition.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Service 3 -->
|
||||
<div class="w-full md:w-1/3 px-4 mb-8">
|
||||
<div class="service-card bg-white rounded-lg filter md:drop-shadow-custom-bg drop-shadow-custom-bg-mobile p-8 h-full">
|
||||
<div class="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mb-6 mx-auto">
|
||||
<svg class="w-8 h-8 text-blue-600" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M5 2a1 1 0 011 1v1h1a1 1 0 010 2H6v1a1 1 0 01-2 0V6H3a1 1 0 010-2h1V3a1 1 0 011-1zm0 10a1 1 0 011 1v1h1a1 1 0 110 2H6v1a1 1 0 11-2 0v-1H3a1 1 0 110-2h1v-1a1 1 0 011-1zM12 2a1 1 0 01.967.744L14.146 7.2 17.5 9.134a1 1 0 010 1.732l-3.354 1.935-1.18 4.455a1 1 0 01-1.933 0L9.854 12.8 6.5 10.866a1 1 0 010-1.732l3.354-1.935 1.18-4.455A1 1 0 0112 2z"
|
||||
clip-rule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-blue-800 mb-4 text-center">Business Valuation</h3>
|
||||
<p class="text-gray-600 text-center">Our expert team provides accurate business valuations based on industry standards, financial performance, and market conditions.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Video Section -->
|
||||
<div class="mt-16 text-center">
|
||||
<h3 class="text-2xl font-semibold text-blue-800 mb-8">See How We Work</h3>
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<video controls class="w-full rounded-lg shadow-xl" poster="assets/images/video-poster.png">
|
||||
<source src="assets/videos/Bizmatch30Spot.mp4" type="video/mp4" />
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us Section -->
|
||||
<section class="py-20 bg-white">
|
||||
<div class="container mx-auto px-6">
|
||||
<div class="text-center mb-16">
|
||||
<h2 class="text-3xl font-bold text-blue-800 mb-4">Why Choose BizMatch</h2>
|
||||
<p class="text-gray-600 max-w-2xl mx-auto">With decades of experience in the business brokerage industry, we provide unparalleled service to our clients.</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap -mx-4">
|
||||
<!-- Feature 1 -->
|
||||
<div class="w-full md:w-1/4 px-4 mb-8">
|
||||
<div class="text-center">
|
||||
<div class="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mb-6 mx-auto">
|
||||
<svg class="w-8 h-8 text-blue-600" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M2.166 4.999A11.954 11.954 0 0010 1.944 11.954 11.954 0 0017.834 5c.11.65.166 1.32.166 2.001 0 5.225-3.34 9.67-8 11.317C5.34 16.67 2 12.225 2 7c0-.682.057-1.35.166-2.001zm11.541 3.708a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||
clip-rule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-blue-800 mb-2">Experience</h3>
|
||||
<p class="text-gray-600">Over 25 years of combined experience in business brokerage.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="w-full md:w-1/4 px-4 mb-8">
|
||||
<div class="text-center">
|
||||
<div class="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mb-6 mx-auto">
|
||||
<svg class="w-8 h-8 text-green-600" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-blue-800 mb-2">Confidentiality</h3>
|
||||
<p class="text-gray-600">We maintain strict confidentiality throughout the entire transaction process.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="w-full md:w-1/4 px-4 mb-8">
|
||||
<div class="text-center">
|
||||
<div class="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center mb-6 mx-auto">
|
||||
<svg class="w-8 h-8 text-purple-600" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M9 6a3 3 0 11-6 0 3 3 0 016 0zM17 6a3 3 0 11-6 0 3 3 0 016 0zM12.93 17c.046-.327.07-.66.07-1a6.97 6.97 0 00-1.5-4.33A5 5 0 0119 16v1h-6.07zM6 11a5 5 0 015 5v1H1v-1a5 5 0 015-5z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-blue-800 mb-2">Network</h3>
|
||||
<p class="text-gray-600">Extensive network of qualified buyers and business owners throughout Texas.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="w-full md:w-1/4 px-4 mb-8">
|
||||
<div class="text-center">
|
||||
<div class="w-16 h-16 bg-yellow-100 rounded-full flex items-center justify-center mb-6 mx-auto">
|
||||
<svg class="w-8 h-8 text-yellow-600" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z"
|
||||
clip-rule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-blue-800 mb-2">Personalized Approach</h3>
|
||||
<p class="text-gray-600">Customized strategy for each client based on their unique business goals.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<!-- ==== ANPASSUNGEN ENDE ==== -->
|
||||
</section>
|
||||
|
||||
<!-- Location Section -->
|
||||
<section id="location" class="py-20 bg-gray-50">
|
||||
<div class="container mx-auto px-6">
|
||||
<div class="flex flex-wrap items-stretch">
|
||||
<!-- Changed from items-center to items-stretch -->
|
||||
<div class="w-full lg:w-2/5 mb-12 lg:mb-0">
|
||||
<div class="h-full flex flex-col">
|
||||
<!-- Added flex container with h-full -->
|
||||
<h2 class="text-3xl font-bold text-blue-800 mb-6">Visit Our Office</h2>
|
||||
<p class="text-gray-600 mb-8 text-lg">Our team of business brokers is ready to assist you at our Corpus Christi location.</p>
|
||||
<div class="bg-white p-6 rounded-lg shadow-lg flex-grow">
|
||||
<!-- Added flex-grow to make it fill available space -->
|
||||
<h3 class="text-xl font-semibold text-blue-800 mb-4">BizMatch Headquarters</h3>
|
||||
<p class="text-gray-600 mb-2">1001 Blucher Street</p>
|
||||
<p class="text-gray-600 mb-2">Corpus Christi, TX 78401</p>
|
||||
<p class="text-gray-600 mb-6">United States</p>
|
||||
<p class="text-gray-600 mb-2"><strong>Phone:</strong> (555) 123-4567</p>
|
||||
<p class="text-gray-600"><strong>Email:</strong> info@bizmatch.net</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full lg:w-3/5">
|
||||
<div class="rounded-lg overflow-hidden shadow-xl h-full min-h-[384px]">
|
||||
<!-- Changed h-96 to h-full with min-height -->
|
||||
<iframe
|
||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3533.7894679685755!2d-97.38527228476843!3d27.773756032788047!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x866c1e3b8a9d0c0b%3A0x8f2c1d4c1a5c5b2c!2s1001%20Blucher%20St%2C%20Corpus%20Christi%2C%20TX%2078401%2C%20USA!5e0!3m2!1sen!2sde!4v1672531192743!5m2!1sen!2sde"
|
||||
width="100%"
|
||||
height="100%"
|
||||
class="rounded-lg border-0"
|
||||
style="min-height: 384px; display: block"
|
||||
allowfullscreen=""
|
||||
loading="lazy"
|
||||
referrerpolicy="no-referrer-when-downgrade"
|
||||
>
|
||||
</iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section id="contact" class="py-20 bg-blue-700">
|
||||
<div class="container mx-auto px-6 text-center">
|
||||
<h2 class="text-3xl font-bold text-white mb-8">Ready to Get Started?</h2>
|
||||
<p class="text-white text-xl mb-12 max-w-3xl mx-auto">Contact our team of experienced business brokers today for a confidential consultation about buying or selling a business.</p>
|
||||
<a routerLink="/emailUs" class="bg-white text-blue-700 font-bold px-8 py-4 rounded-lg shadow-lg hover:bg-gray-100 transition duration-300 text-lg">Contact Us Now</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Footer -->
|
||||
|
|
|
|||
|
|
@ -1,72 +1,85 @@
|
|||
.bg-cover-custom {
|
||||
background-image: url('/assets/images/index-bg.webp');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
border-radius: 20px;
|
||||
}
|
||||
select:not([size]) {
|
||||
background-image: unset;
|
||||
}
|
||||
[type='text'],
|
||||
[type='email'],
|
||||
[type='url'],
|
||||
[type='password'],
|
||||
[type='number'],
|
||||
[type='date'],
|
||||
[type='datetime-local'],
|
||||
[type='month'],
|
||||
[type='search'],
|
||||
[type='tel'],
|
||||
[type='time'],
|
||||
[type='week'],
|
||||
[multiple],
|
||||
textarea,
|
||||
select {
|
||||
border: unset;
|
||||
}
|
||||
.toggle-checkbox:checked {
|
||||
right: 0;
|
||||
border-color: rgb(125 211 252);
|
||||
}
|
||||
.toggle-checkbox:checked + .toggle-label {
|
||||
background-color: rgb(125 211 252);
|
||||
}
|
||||
:host ::ng-deep .ng-select.ng-select-single .ng-select-container {
|
||||
height: 48px;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
.ng-value-container .ng-input {
|
||||
top: 10px;
|
||||
}
|
||||
span.ng-arrow-wrapper {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
select {
|
||||
color: #000; /* Standard-Textfarbe für das Dropdown */
|
||||
// background-color: #fff; /* Hintergrundfarbe für das Dropdown */
|
||||
// Hero section styles
|
||||
.hero-section {
|
||||
background: linear-gradient(135deg, #0046b5 0%, #00a0e9 100%);
|
||||
// height: 70vh; // Made shorter as requested
|
||||
// min-height: 500px; // Reduced from 600px
|
||||
}
|
||||
|
||||
select option {
|
||||
color: #000; /* Textfarbe für Dropdown-Optionen */
|
||||
// Button hover effects
|
||||
.btn-primary {
|
||||
background-color: #0046b5;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: #003492;
|
||||
}
|
||||
}
|
||||
|
||||
select.placeholder-selected {
|
||||
color: #999; /* Farbe für den Platzhalter */
|
||||
// Service card animation
|
||||
.service-card {
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
input::placeholder {
|
||||
color: #555; /* Dunkleres Grau */
|
||||
opacity: 1; /* Stellt sicher, dass die Deckkraft 100% ist */
|
||||
}
|
||||
|
||||
/* Stellt sicher, dass die Optionen im Dropdown immer schwarz sind */
|
||||
select:focus option,
|
||||
select:hover option {
|
||||
color: #000 !important;
|
||||
// Responsive adjustments
|
||||
@media (max-width: 768px) {
|
||||
.hero-section {
|
||||
height: auto;
|
||||
padding: 4rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the Google Map is responsive
|
||||
google-map {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// Override Tailwind default styling for video
|
||||
video {
|
||||
max-width: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
// Zusätzliche Styles für den Location-Bereich
|
||||
|
||||
// Verbesserte Map-Container Styles
|
||||
#location {
|
||||
.rounded-lg.overflow-hidden {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
min-height: 384px;
|
||||
}
|
||||
|
||||
iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
// Stellen Sie sicher, dass der Kartencontainer im mobilen Layout
|
||||
// eine angemessene Höhe hat
|
||||
@media (max-width: 1023px) {
|
||||
.rounded-lg.overflow-hidden {
|
||||
height: 400px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adressbox-Styling verbessern
|
||||
.bg-white.p-6.rounded-lg.shadow-lg.flex-grow {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
// Sicherstellen, dass der untere Bereich sichtbar bleibt
|
||||
.contact-info {
|
||||
margin-top: auto;
|
||||
}
|
||||
input[type='text'][name='aiSearchText'] {
|
||||
padding: 14px; /* Innerer Abstand */
|
||||
font-size: 16px; /* Schriftgröße anpassen */
|
||||
box-sizing: border-box; /* Padding und Border in die Höhe und Breite einrechnen */
|
||||
height: 48px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,313 +1,52 @@
|
|||
import { CommonModule } from '@angular/common';
|
||||
import { ChangeDetectorRef, Component, ElementRef, ViewChild } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||
import { NgSelectModule } from '@ng-select/ng-select';
|
||||
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
||||
import { initFlowbite } from 'flowbite';
|
||||
import { catchError, concat, debounceTime, distinctUntilChanged, lastValueFrom, Observable, of, Subject, Subscription, switchMap, tap } from 'rxjs';
|
||||
import { BusinessListingCriteria, CityAndStateResult, CommercialPropertyListingCriteria, GeoResult, KeycloakUser, UserListingCriteria } from '../../../../../bizmatch-server/src/models/main.model';
|
||||
import { ModalService } from '../../components/search-modal/modal.service';
|
||||
import { TooltipComponent } from '../../components/tooltip/tooltip.component';
|
||||
import { AiService } from '../../services/ai.service';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { RouterLink, RouterOutlet } from '@angular/router';
|
||||
import { AuthService } from '../../services/auth.service';
|
||||
import { CriteriaChangeService } from '../../services/criteria-change.service';
|
||||
import { GeoService } from '../../services/geo.service';
|
||||
import { ListingsService } from '../../services/listings.service';
|
||||
import { SearchService } from '../../services/search.service';
|
||||
import { SelectOptionsService } from '../../services/select-options.service';
|
||||
|
||||
import { User } from '../../../../../bizmatch-server/src/models/db.model';
|
||||
import { KeycloakUser } from '../../../../../bizmatch-server/src/models/main.model';
|
||||
import { UserService } from '../../services/user.service';
|
||||
import {
|
||||
assignProperties,
|
||||
compareObjects,
|
||||
createEmptyBusinessListingCriteria,
|
||||
createEmptyCommercialPropertyListingCriteria,
|
||||
createEmptyUserListingCriteria,
|
||||
createEnhancedProxy,
|
||||
getCriteriaStateObject,
|
||||
map2User,
|
||||
} from '../../utils/utils';
|
||||
@UntilDestroy()
|
||||
import { map2User } from '../../utils/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
standalone: true,
|
||||
imports: [CommonModule, FormsModule, RouterModule, NgSelectModule, TooltipComponent],
|
||||
templateUrl: './home.component.html',
|
||||
styleUrl: './home.component.scss',
|
||||
styleUrls: ['./home.component.scss'],
|
||||
standalone: true,
|
||||
imports: [CommonModule, RouterOutlet, RouterLink],
|
||||
})
|
||||
export class HomeComponent {
|
||||
placeholders: string[] = ['Property close to Houston less than 10M', 'Franchise business in Austin price less than 500K'];
|
||||
activeTabAction: 'business' | 'commercialProperty' | 'broker' = 'business';
|
||||
type: string;
|
||||
maxPrice: string;
|
||||
minPrice: string;
|
||||
criteria: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria;
|
||||
states = [];
|
||||
isMenuOpen = false;
|
||||
user: KeycloakUser;
|
||||
prompt: string;
|
||||
cities$: Observable<CityAndStateResult[]>;
|
||||
cityLoading = false;
|
||||
cityInput$ = new Subject<string>();
|
||||
cityOrState = undefined;
|
||||
private criteriaChangeSubscription: Subscription;
|
||||
numberOfResults$: Observable<number>;
|
||||
numberOfBroker$: Observable<number>;
|
||||
numberOfCommercial$: Observable<number>;
|
||||
aiSearch = false;
|
||||
aiSearchText = '';
|
||||
aiSearchFailed = false;
|
||||
loadingAi = false;
|
||||
@ViewChild('aiSearchInput', { static: false }) searchInput!: ElementRef;
|
||||
typingSpeed: number = 100; // Geschwindigkeit des Tippens (ms)
|
||||
pauseTime: number = 2000; // Pausezeit, bevor der Text verschwindet (ms)
|
||||
index: number = 0;
|
||||
charIndex: number = 0;
|
||||
typingInterval: any;
|
||||
showInput: boolean = true; // Steuerung der Anzeige des Eingabefelds
|
||||
tooltipTargetBeta = 'tooltipTargetBeta';
|
||||
public constructor(
|
||||
private router: Router,
|
||||
private modalService: ModalService,
|
||||
private searchService: SearchService,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
public selectOptions: SelectOptionsService,
|
||||
export class HomeComponent implements OnInit {
|
||||
showMobileMenu = false;
|
||||
keycloakUser: KeycloakUser;
|
||||
user: User;
|
||||
constructor(private authService: AuthService, private userService: UserService) {}
|
||||
|
||||
private criteriaChangeService: CriteriaChangeService,
|
||||
private geoService: GeoService,
|
||||
public cdRef: ChangeDetectorRef,
|
||||
private listingService: ListingsService,
|
||||
private userService: UserService,
|
||||
private aiService: AiService,
|
||||
private authService: AuthService,
|
||||
) {}
|
||||
async ngOnInit() {
|
||||
setTimeout(() => {
|
||||
initFlowbite();
|
||||
}, 0);
|
||||
this.numberOfBroker$ = this.userService.getNumberOfBroker(createEmptyUserListingCriteria());
|
||||
this.numberOfCommercial$ = this.listingService.getNumberOfListings(createEmptyCommercialPropertyListingCriteria(), 'commercialProperty');
|
||||
// Add smooth scrolling for anchor links
|
||||
this.setupSmoothScrolling();
|
||||
const token = await this.authService.getToken();
|
||||
sessionStorage.removeItem('businessListings');
|
||||
sessionStorage.removeItem('commercialPropertyListings');
|
||||
sessionStorage.removeItem('brokerListings');
|
||||
this.criteria = createEnhancedProxy(getCriteriaStateObject('businessListings'), this);
|
||||
this.user = map2User(token);
|
||||
this.loadCities();
|
||||
this.setupCriteriaChangeListener();
|
||||
}
|
||||
async changeTab(tabname: 'business' | 'commercialProperty' | 'broker') {
|
||||
this.activeTabAction = tabname;
|
||||
this.cityOrState = null;
|
||||
if ('business' === tabname) {
|
||||
this.criteria = createEnhancedProxy(getCriteriaStateObject('businessListings'), this);
|
||||
} else if ('commercialProperty' === tabname) {
|
||||
this.criteria = createEnhancedProxy(getCriteriaStateObject('commercialPropertyListings'), this);
|
||||
} else if ('broker' === tabname) {
|
||||
this.criteria = createEnhancedProxy(getCriteriaStateObject('brokerListings'), this);
|
||||
} else {
|
||||
this.criteria = undefined;
|
||||
this.keycloakUser = map2User(token);
|
||||
if (this.keycloakUser) {
|
||||
this.user = await this.userService.getByMail(this.keycloakUser.email);
|
||||
this.userService.changeUser(this.user);
|
||||
}
|
||||
}
|
||||
|
||||
search() {
|
||||
this.router.navigate([`${this.activeTabAction}Listings`]);
|
||||
}
|
||||
private setupCriteriaChangeListener() {
|
||||
this.criteriaChangeSubscription = this.criteriaChangeService.criteriaChange$.pipe(untilDestroyed(this), debounceTime(400)).subscribe(() => this.setTotalNumberOfResults());
|
||||
toggleMobileMenu(): void {
|
||||
this.showMobileMenu = !this.showMobileMenu;
|
||||
}
|
||||
|
||||
toggleMenu() {
|
||||
this.isMenuOpen = !this.isMenuOpen;
|
||||
}
|
||||
onTypesChange(value) {
|
||||
if (value === '') {
|
||||
// Wenn keine Option ausgewählt ist, setzen Sie types zurück auf ein leeres Array
|
||||
this.criteria.types = [];
|
||||
} else {
|
||||
this.criteria.types = [value];
|
||||
}
|
||||
}
|
||||
onRadiusChange(value) {
|
||||
if (value === 'null') {
|
||||
// Wenn keine Option ausgewählt ist, setzen Sie types zurück auf ein leeres Array
|
||||
this.criteria.radius = null;
|
||||
} else {
|
||||
this.criteria.radius = parseInt(value);
|
||||
}
|
||||
}
|
||||
async openModal() {
|
||||
const accepted = await this.modalService.showModal(this.criteria);
|
||||
if (accepted) {
|
||||
this.router.navigate([`${this.activeTabAction}Listings`]);
|
||||
}
|
||||
}
|
||||
private loadCities() {
|
||||
this.cities$ = concat(
|
||||
of([]), // default items
|
||||
this.cityInput$.pipe(
|
||||
distinctUntilChanged(),
|
||||
tap(() => (this.cityLoading = true)),
|
||||
switchMap(term =>
|
||||
//this.geoService.findCitiesStartingWith(term).pipe(
|
||||
this.geoService.findCitiesAndStatesStartingWith(term).pipe(
|
||||
catchError(() => of([])), // empty list on error
|
||||
// map(cities => cities.map(city => city.city)), // transform the list of objects to a list of city names
|
||||
tap(() => (this.cityLoading = false)),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
trackByFn(item: GeoResult) {
|
||||
return item.id;
|
||||
}
|
||||
setCityOrState(cityOrState: CityAndStateResult) {
|
||||
if (cityOrState) {
|
||||
if (cityOrState.type === 'state') {
|
||||
this.criteria.state = cityOrState.content.state_code;
|
||||
} else {
|
||||
this.criteria.city = cityOrState.content as GeoResult;
|
||||
this.criteria.state = cityOrState.content.state;
|
||||
this.criteria.searchType = 'radius';
|
||||
this.criteria.radius = 20;
|
||||
}
|
||||
} else {
|
||||
this.criteria.state = null;
|
||||
this.criteria.city = null;
|
||||
this.criteria.radius = null;
|
||||
this.criteria.searchType = 'exact';
|
||||
}
|
||||
}
|
||||
getTypes() {
|
||||
if (this.criteria.criteriaType === 'businessListings') {
|
||||
return this.selectOptions.typesOfBusiness;
|
||||
} else if (this.criteria.criteriaType === 'commercialPropertyListings') {
|
||||
return this.selectOptions.typesOfCommercialProperty;
|
||||
} else {
|
||||
return this.selectOptions.customerSubTypes;
|
||||
}
|
||||
}
|
||||
getPlaceholderLabel() {
|
||||
if (this.criteria.criteriaType === 'businessListings') {
|
||||
return 'Business Type';
|
||||
} else if (this.criteria.criteriaType === 'commercialPropertyListings') {
|
||||
return 'Property Type';
|
||||
} else {
|
||||
return 'Professional Type';
|
||||
}
|
||||
}
|
||||
setTotalNumberOfResults() {
|
||||
if (this.criteria) {
|
||||
console.log(`Getting total number of results for ${this.criteria.criteriaType}`);
|
||||
if (this.criteria.criteriaType === 'businessListings' || this.criteria.criteriaType === 'commercialPropertyListings') {
|
||||
this.numberOfResults$ = this.listingService.getNumberOfListings(this.criteria, this.criteria.criteriaType === 'businessListings' ? 'business' : 'commercialProperty');
|
||||
} else if (this.criteria.criteriaType === 'brokerListings') {
|
||||
this.numberOfResults$ = this.userService.getNumberOfBroker(this.criteria);
|
||||
} else {
|
||||
this.numberOfResults$ = of();
|
||||
}
|
||||
}
|
||||
}
|
||||
getNumberOfFiltersSet() {
|
||||
if (this.criteria?.criteriaType === 'brokerListings') {
|
||||
return compareObjects(createEmptyUserListingCriteria(), this.criteria, ['start', 'length', 'page', 'searchType', 'radius']);
|
||||
} else if (this.criteria?.criteriaType === 'businessListings') {
|
||||
return compareObjects(createEmptyBusinessListingCriteria(), this.criteria, ['start', 'length', 'page', 'searchType', 'radius']);
|
||||
} else if (this.criteria?.criteriaType === 'commercialPropertyListings') {
|
||||
return compareObjects(createEmptyCommercialPropertyListingCriteria(), this.criteria, ['start', 'length', 'page', 'searchType', 'radius']);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
toggleAiSearch() {
|
||||
this.aiSearch = !this.aiSearch;
|
||||
this.aiSearchFailed = false;
|
||||
if (!this.aiSearch) {
|
||||
this.aiSearchText = '';
|
||||
this.stopTypingEffect();
|
||||
} else {
|
||||
setTimeout(() => this.startTypingEffect(), 0);
|
||||
}
|
||||
}
|
||||
ngOnDestroy(): void {
|
||||
clearTimeout(this.typingInterval); // Stelle sicher, dass das Intervall gestoppt wird, wenn die Komponente zerstört wird
|
||||
}
|
||||
|
||||
startTypingEffect(): void {
|
||||
if (!this.aiSearchText) {
|
||||
this.typePlaceholder();
|
||||
}
|
||||
}
|
||||
|
||||
stopTypingEffect(): void {
|
||||
clearTimeout(this.typingInterval);
|
||||
}
|
||||
typePlaceholder(): void {
|
||||
if (!this.searchInput || !this.searchInput.nativeElement) {
|
||||
return; // Falls das Eingabefeld nicht verfügbar ist (z.B. durch ngIf)
|
||||
}
|
||||
|
||||
if (this.aiSearchText) {
|
||||
return; // Stoppe, wenn der Benutzer Text eingegeben hat
|
||||
}
|
||||
|
||||
const inputField = this.searchInput.nativeElement as HTMLInputElement;
|
||||
if (document.activeElement === inputField) {
|
||||
this.stopTypingEffect();
|
||||
return;
|
||||
}
|
||||
|
||||
inputField.placeholder = this.placeholders[this.index].substring(0, this.charIndex);
|
||||
|
||||
if (this.charIndex < this.placeholders[this.index].length) {
|
||||
this.charIndex++;
|
||||
this.typingInterval = setTimeout(() => this.typePlaceholder(), this.typingSpeed);
|
||||
} else {
|
||||
// Nach dem vollständigen Tippen eine Pause einlegen
|
||||
this.typingInterval = setTimeout(() => {
|
||||
inputField.placeholder = ''; // Schlagartiges Löschen des Platzhalters
|
||||
this.charIndex = 0;
|
||||
this.index = (this.index + 1) % this.placeholders.length;
|
||||
this.typingInterval = setTimeout(() => this.typePlaceholder(), this.typingSpeed);
|
||||
}, this.pauseTime);
|
||||
}
|
||||
}
|
||||
async generateAiResponse() {
|
||||
this.loadingAi = true;
|
||||
this.aiSearchFailed = false;
|
||||
try {
|
||||
const result = await this.aiService.generateAiReponse(this.aiSearchText);
|
||||
let criteria: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria | any;
|
||||
if (result.criteriaType === 'businessListings') {
|
||||
this.changeTab('business');
|
||||
criteria = result as BusinessListingCriteria;
|
||||
} else if (result.criteriaType === 'commercialPropertyListings') {
|
||||
this.changeTab('commercialProperty');
|
||||
criteria = result as CommercialPropertyListingCriteria;
|
||||
} else {
|
||||
this.changeTab('broker');
|
||||
criteria = result as UserListingCriteria;
|
||||
}
|
||||
const city = criteria.city as string;
|
||||
if (city && city.length > 0) {
|
||||
let results = await lastValueFrom(this.geoService.findCitiesStartingWith(city, criteria.state));
|
||||
if (results.length > 0) {
|
||||
criteria.city = results[0];
|
||||
} else {
|
||||
criteria.city = null;
|
||||
}
|
||||
}
|
||||
if (criteria.radius && criteria.radius.length > 0) {
|
||||
criteria.radius = parseInt(criteria.radius);
|
||||
}
|
||||
this.loadingAi = false;
|
||||
this.criteria = assignProperties(this.criteria, criteria);
|
||||
this.search();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
this.aiSearchFailed = true;
|
||||
this.loadingAi = false;
|
||||
private setupSmoothScrolling(): void {
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
const target = document.querySelector((this as HTMLAnchorElement).getAttribute('href') || '');
|
||||
if (target) {
|
||||
target.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,9 +77,9 @@
|
|||
<span class="bg-blue-100 text-blue-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300">ADMIN</span>
|
||||
</div>
|
||||
|
||||
}@else{
|
||||
<app-validated-select label="Customer Type" name="customerType" [(ngModel)]="user.customerType" [options]="customerTypeOptions"></app-validated-select>
|
||||
} @if (isProfessional){
|
||||
}
|
||||
<app-validated-select [disabled]="true" label="Customer Type" name="customerType" [(ngModel)]="user.customerType" [options]="customerTypeOptions"></app-validated-select>
|
||||
@if (isProfessional){
|
||||
<!-- <div>
|
||||
<label for="customerSubType" class="block text-sm font-medium text-gray-700">Professional Type</label>
|
||||
<select id="customerSubType" name="customerSubType" [(ngModel)]="user.customerSubType" required class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
|
||||
|
|
@ -220,7 +220,7 @@
|
|||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="flex items-center !my-8">
|
||||
<!-- <div class="flex items-center !my-8">
|
||||
<label class="flex items-center cursor-pointer">
|
||||
<div class="relative">
|
||||
<input type="checkbox" [(ngModel)]="user.showInDirectory" name="showInDirectory" class="hidden" />
|
||||
|
|
@ -228,7 +228,7 @@
|
|||
</div>
|
||||
<div class="ml-3 text-gray-700 font-medium">Show your profile in Professional Directory</div>
|
||||
</label>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="flex justify-start">
|
||||
<button type="submit" class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" (click)="updateProfile(user)">
|
||||
|
|
|
|||
|
|
@ -130,38 +130,6 @@ export class AccountComponent {
|
|||
label: this.titleCasePipe.transform(type.name),
|
||||
}));
|
||||
}
|
||||
// async synchronizeSubscriptions(subscriptions: StripeSubscription[]) {
|
||||
// let changed = false;
|
||||
// if (this.isAdmin()) {
|
||||
// return;
|
||||
// }
|
||||
// if (this.subscriptions.length === 0) {
|
||||
// if (!this.user.subscriptionPlan) {
|
||||
// this.router.navigate(['pricing']);
|
||||
// } else {
|
||||
// this.subscriptions = [{ ended_at: null, start_date: Math.floor(new Date(this.user.created).getTime() / 1000), status: null, metadata: { plan: 'Free Plan' } }];
|
||||
// changed = checkAndUpdate(changed, this.user.customerType !== 'buyer' && this.user.customerType !== 'seller', () => (this.user.customerType = 'buyer'));
|
||||
// changed = checkAndUpdate(changed, !!this.user.customerSubType, () => (this.user.customerSubType = null));
|
||||
// changed = checkAndUpdate(changed, this.user.subscriptionPlan !== 'free', () => (this.user.subscriptionPlan = 'free'));
|
||||
// changed = checkAndUpdate(changed, !!this.user.subscriptionId, () => (this.user.subscriptionId = null));
|
||||
// }
|
||||
// } else {
|
||||
// const subscription = subscriptions[0];
|
||||
// changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Broker Plan' && this.user.customerType !== 'professional', () => (this.user.customerType = 'professional'));
|
||||
// changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Broker Plan' && this.user.customerSubType !== 'broker', () => (this.user.customerSubType = 'broker'));
|
||||
// changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Broker Plan' && this.user.subscriptionPlan !== 'broker', () => (this.user.subscriptionPlan = 'broker'));
|
||||
// changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Broker Plan' && !this.user.subscriptionId, () => (this.user.subscriptionId = subscription.id));
|
||||
|
||||
// changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Professional Plan' && this.user.customerType !== 'professional', () => (this.user.customerType = 'professional'));
|
||||
// changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Professional Plan' && this.user.subscriptionPlan !== 'professional', () => (this.user.subscriptionPlan = 'professional'));
|
||||
// changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Professional Plan' && this.user.subscriptionId !== 'professional', () => (this.user.subscriptionId = subscription.id));
|
||||
// }
|
||||
// if (changed) {
|
||||
// await this.userService.saveGuaranteed(this.user);
|
||||
// this.cdref.detectChanges();
|
||||
// this.cdref.markForCheck();
|
||||
// }
|
||||
// }
|
||||
|
||||
ngOnDestroy() {
|
||||
this.validationMessagesService.clearMessages(); // Löschen Sie alle bestehenden Validierungsnachrichten
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<div class="mb-4">
|
||||
<label for="listingsCategory" class="block text-sm font-bold text-gray-700 mb-1">Listing category</label>
|
||||
<ng-select
|
||||
[readonly]="mode === 'edit'"
|
||||
[readonly]="true"
|
||||
[items]="selectOptions?.listingCategories"
|
||||
bindLabel="name"
|
||||
bindValue="value"
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 171 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 182 KiB |
Binary file not shown.
|
|
@ -12,7 +12,6 @@
|
|||
@import 'tailwindcss/utilities';
|
||||
@import 'ngx-sharebuttons/themes/default';
|
||||
/* styles.scss */
|
||||
@import 'leaflet/dist/leaflet.css';
|
||||
:root {
|
||||
--text-color-secondary: rgba(255, 255, 255);
|
||||
--wrapper-width: 1491px;
|
||||
|
|
@ -115,20 +114,3 @@ input::placeholder,
|
|||
textarea::placeholder {
|
||||
color: #999 !important;
|
||||
}
|
||||
|
||||
/* Fix für Marker-Icons in Leaflet */
|
||||
.leaflet-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.leaflet-marker-icon {
|
||||
/* Optional: Anpassen der Marker-Icon-Größe */
|
||||
width: 25px;
|
||||
height: 41px;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue