First version AI Search
This commit is contained in:
@@ -0,0 +1 @@
|
||||
<p>dropdown works!</p>
|
||||
129
bizmatch/src/app/components/dropdown/dropdown.component.ts
Normal file
129
bizmatch/src/app/components/dropdown/dropdown.component.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import { AfterViewInit, Component, ElementRef, HostBinding, Input, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { createPopper, Instance as PopperInstance } from '@popperjs/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dropdown',
|
||||
template: `
|
||||
<div #targetEl [class.hidden]="!isVisible" class="z-10">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
`,
|
||||
standalone: true,
|
||||
})
|
||||
export class DropdownComponent implements AfterViewInit, OnDestroy {
|
||||
@ViewChild('targetEl') targetEl!: ElementRef<HTMLElement>;
|
||||
@Input() triggerEl!: HTMLElement;
|
||||
|
||||
@Input() placement: any = 'bottom';
|
||||
@Input() triggerType: 'click' | 'hover' = 'click';
|
||||
@Input() offsetSkidding: number = 0;
|
||||
@Input() offsetDistance: number = 10;
|
||||
@Input() delay: number = 300;
|
||||
@Input() ignoreClickOutsideClass: string | false = false;
|
||||
|
||||
@HostBinding('class.hidden') isHidden: boolean = true;
|
||||
|
||||
private popperInstance: PopperInstance | null = null;
|
||||
isVisible: boolean = false;
|
||||
private clickOutsideListener: any;
|
||||
private hoverShowListener: any;
|
||||
private hoverHideListener: any;
|
||||
|
||||
ngAfterViewInit() {
|
||||
if (!this.triggerEl) {
|
||||
console.error('Trigger element is not provided to the dropdown component.');
|
||||
return;
|
||||
}
|
||||
this.initializePopper();
|
||||
this.setupEventListeners();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroyPopper();
|
||||
this.removeEventListeners();
|
||||
}
|
||||
|
||||
private initializePopper() {
|
||||
this.popperInstance = createPopper(this.triggerEl, this.targetEl.nativeElement, {
|
||||
placement: this.placement,
|
||||
modifiers: [
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [this.offsetSkidding, this.offsetDistance],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
private setupEventListeners() {
|
||||
if (this.triggerType === 'click') {
|
||||
this.triggerEl.addEventListener('click', () => this.toggle());
|
||||
} else if (this.triggerType === 'hover') {
|
||||
this.hoverShowListener = () => this.show();
|
||||
this.hoverHideListener = () => this.hide();
|
||||
this.triggerEl.addEventListener('mouseenter', this.hoverShowListener);
|
||||
this.triggerEl.addEventListener('mouseleave', this.hoverHideListener);
|
||||
this.targetEl.nativeElement.addEventListener('mouseenter', this.hoverShowListener);
|
||||
this.targetEl.nativeElement.addEventListener('mouseleave', this.hoverHideListener);
|
||||
}
|
||||
|
||||
this.clickOutsideListener = (event: MouseEvent) => this.handleClickOutside(event);
|
||||
document.addEventListener('click', this.clickOutsideListener);
|
||||
}
|
||||
|
||||
private removeEventListeners() {
|
||||
if (this.triggerType === 'click') {
|
||||
this.triggerEl.removeEventListener('click', () => this.toggle());
|
||||
} else if (this.triggerType === 'hover') {
|
||||
this.triggerEl.removeEventListener('mouseenter', this.hoverShowListener);
|
||||
this.triggerEl.removeEventListener('mouseleave', this.hoverHideListener);
|
||||
this.targetEl.nativeElement.removeEventListener('mouseenter', this.hoverShowListener);
|
||||
this.targetEl.nativeElement.removeEventListener('mouseleave', this.hoverHideListener);
|
||||
}
|
||||
|
||||
document.removeEventListener('click', this.clickOutsideListener);
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.isVisible ? this.hide() : this.show();
|
||||
}
|
||||
|
||||
show() {
|
||||
this.isVisible = true;
|
||||
this.isHidden = false;
|
||||
this.targetEl.nativeElement.classList.remove('hidden');
|
||||
this.popperInstance?.update();
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.isVisible = false;
|
||||
this.isHidden = true;
|
||||
this.targetEl.nativeElement.classList.add('hidden');
|
||||
}
|
||||
|
||||
private handleClickOutside(event: MouseEvent) {
|
||||
if (!this.isVisible) return;
|
||||
|
||||
const clickedElement = event.target as HTMLElement;
|
||||
if (this.ignoreClickOutsideClass) {
|
||||
const ignoredElements = document.querySelectorAll(`.${this.ignoreClickOutsideClass}`);
|
||||
const arr = Array.from(ignoredElements);
|
||||
for (const el of arr) {
|
||||
if (el.contains(clickedElement)) return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.targetEl.nativeElement.contains(clickedElement) && !this.triggerEl.contains(clickedElement)) {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
private destroyPopper() {
|
||||
if (this.popperInstance) {
|
||||
this.popperInstance.destroy();
|
||||
this.popperInstance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NavigationEnd, Router, RouterModule } from '@angular/router';
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
||||
import { initFlowbite } from 'flowbite';
|
||||
@Component({
|
||||
@@ -15,7 +15,12 @@ export class FooterComponent {
|
||||
privacyVisible = false;
|
||||
termsVisible = false;
|
||||
currentYear: number = new Date().getFullYear();
|
||||
constructor(private router: Router) {}
|
||||
ngOnInit() {
|
||||
initFlowbite();
|
||||
this.router.events.subscribe(event => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
initFlowbite();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,114 @@
|
||||
<!-- <div class="wrapper">
|
||||
<div class="pl-3 flex align-items-center gap-2">
|
||||
<a routerLink="/home"><img src="assets/images/header-logo.png" height="40" alt="bizmatch" /></a>
|
||||
<p-tabMenu [model]="tabItems" ariaLabelledBy="label" styleClass="flex" [activeItem]="activeItem"> </p-tabMenu>
|
||||
<p-menubar [model]="menuItems"></p-menubar>
|
||||
<p-menubar [model]="loginItems"></p-menubar>
|
||||
@if(user){
|
||||
<div>Welcome, {{ user.firstName }}</div>
|
||||
}
|
||||
<ng-template #empty> </ng-template>
|
||||
<!-- <nav class="bg-white border-gray-200 dark:bg-gray-900">
|
||||
<div class="max-w-screen-xl 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>
|
||||
<div class="flex items-center md:order-2 space-x-3 md:space-x-0 rtl:space-x-reverse">
|
||||
<button
|
||||
type="button"
|
||||
class="flex text-sm bg-gray-200 rounded-full md:me-0 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
|
||||
id="user-menu-button"
|
||||
aria-expanded="false"
|
||||
[attr.data-dropdown-toggle]="user ? 'user-login' : 'user-unknown'"
|
||||
data-dropdown-placement="bottom"
|
||||
>
|
||||
<span class="sr-only">Open user menu</span>
|
||||
@if(user){
|
||||
<img class="w-8 h-8 rounded-full object-cover" src="{{ profileUrl }}" alt="user photo" />
|
||||
} @else {
|
||||
<i class="flex justify-center items-center text-stone-50 w-8 h-8 rounded-full fa-solid fa-bars"></i>
|
||||
}
|
||||
</button>
|
||||
@if(user){
|
||||
<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-login">
|
||||
<div class="px-4 py-3">
|
||||
<span class="block text-sm text-gray-900 dark:text-white">Welcome, {{ user.firstname }} </span>
|
||||
<span class="block text-sm text-gray-500 truncate dark:text-gray-400">{{ user.email }}</span>
|
||||
</div>
|
||||
<ul class="py-2" aria-labelledby="user-menu-button">
|
||||
<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>
|
||||
<li>
|
||||
<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
|
||||
>
|
||||
</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="/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>
|
||||
</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">
|
||||
<ul class="py-2" aria-labelledby="user-menu-button">
|
||||
<li>
|
||||
<a (click)="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>
|
||||
<a (click)="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">Register</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
<button
|
||||
data-collapse-toggle="navbar-user"
|
||||
type="button"
|
||||
class="inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600"
|
||||
aria-controls="navbar-user"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="sr-only">Open main menu</span>
|
||||
<svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<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"
|
||||
>
|
||||
<li>
|
||||
<a
|
||||
routerLinkActive="active-link"
|
||||
routerLink="/businessListings"
|
||||
[ngClass]="{ 'bg-blue-700 text-white md:text-blue-700 md:bg-transparent md:dark:text-blue-500': isActive('/businessListings') }"
|
||||
class="block py-2 px-3 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700"
|
||||
aria-current="page"
|
||||
(click)="closeMenus()"
|
||||
>Businesses</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
routerLinkActive="active-link"
|
||||
routerLink="/commercialPropertyListings"
|
||||
[ngClass]="{ 'bg-blue-700 text-white md:text-blue-700 md:bg-transparent md:dark:text-blue-500': isActive('/commercialPropertyListings') }"
|
||||
class="block py-2 px-3 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700"
|
||||
(click)="closeMenus()"
|
||||
>Properties</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
routerLinkActive="active-link"
|
||||
routerLink="/brokerListings"
|
||||
[ngClass]="{ 'bg-blue-700 text-white md:text-blue-700 md:bg-transparent md:dark:text-blue-500': isActive('/brokerListings') }"
|
||||
class="block py-2 px-3 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700"
|
||||
(click)="closeMenus()"
|
||||
>Professionals</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</nav> -->
|
||||
|
||||
<nav class="bg-white border-gray-200 dark:bg-gray-900">
|
||||
<div class="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4">
|
||||
@@ -17,6 +116,16 @@
|
||||
<img src="assets/images/header-logo.png" class="h-8" alt="Flowbite Logo" />
|
||||
</a>
|
||||
<div class="flex items-center md:order-2 space-x-3 md:space-x-0 rtl:space-x-reverse">
|
||||
<!-- Filter button -->
|
||||
<button
|
||||
type="button"
|
||||
#triggerButton
|
||||
id="filterDropdownButton"
|
||||
class="max-sm:hidden px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 md:me-2"
|
||||
>
|
||||
<i class="fas fa-filter mr-2"></i>Filter (1)
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="flex text-sm bg-gray-200 rounded-full md:me-0 focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
|
||||
@@ -122,4 +231,170 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Mobile filter button -->
|
||||
<!-- <div class="md:hidden flex justify-center pb-4">
|
||||
<button
|
||||
data-dropdown-toggle="filterDropdown"
|
||||
type="button"
|
||||
id="filterDropdownMobileButton"
|
||||
class="w-full mx-4 px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
||||
>
|
||||
<i class="fas fa-filter mr-2"></i>Filter (1)
|
||||
</button>
|
||||
</div> -->
|
||||
</nav>
|
||||
<!-- ############################### -->
|
||||
<!-- Filter Dropdown -->
|
||||
<!-- ############################### -->
|
||||
<app-dropdown [triggerEl]="triggerButton" [triggerType]="'click'">
|
||||
<div id="filterDropdown" class="z-10 w-80 p-3 bg-slate-200 rounded-lg shadow-lg dark:bg-gray-700">
|
||||
<h3 class="mb-3 text-sm font-medium text-gray-900 dark:text-white">Filter</h3>
|
||||
|
||||
<!-- Price Range -->
|
||||
<div class="mb-4">
|
||||
<div class="flex items-center space-x-4">
|
||||
<input
|
||||
type="text"
|
||||
[ngModel]="prompt"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
value="300"
|
||||
/>
|
||||
</div>
|
||||
<!-- <label for="price-range" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Price Range</label>
|
||||
<div class="flex items-center space-x-4">
|
||||
<input
|
||||
type="number"
|
||||
id="price-from"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="From"
|
||||
value="300"
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
id="price-to"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="To"
|
||||
value="3500"
|
||||
/>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<!-- Sales -->
|
||||
<!-- <div class="mb-4">
|
||||
<label for="sales-range" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Sales</label>
|
||||
<div class="flex items-center space-x-4">
|
||||
<input
|
||||
type="number"
|
||||
id="sales-from"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="From"
|
||||
value="1"
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
id="sales-to"
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="To"
|
||||
value="100"
|
||||
/>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- Category -->
|
||||
<!-- <div class="mb-4">
|
||||
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Category</label>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<button
|
||||
class="px-3 py-1 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-blue-500 dark:focus:text-white"
|
||||
>
|
||||
Gaming
|
||||
</button>
|
||||
<button
|
||||
class="px-3 py-1 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-blue-500 dark:focus:text-white"
|
||||
>
|
||||
Electronics
|
||||
</button>
|
||||
<button
|
||||
class="px-3 py-1 text-sm font-medium text-white bg-blue-700 border border-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
|
||||
>
|
||||
Phone
|
||||
</button>
|
||||
<button
|
||||
class="px-3 py-1 text-sm font-medium text-white bg-blue-700 border border-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
|
||||
>
|
||||
TV/Monitor
|
||||
</button>
|
||||
<button
|
||||
class="px-3 py-1 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-blue-500 dark:focus:text-white"
|
||||
>
|
||||
Laptop
|
||||
</button>
|
||||
<button
|
||||
class="px-3 py-1 text-sm font-medium text-white bg-blue-700 border border-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
|
||||
>
|
||||
Watch
|
||||
</button>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- State -->
|
||||
<!-- <div class="mb-4">
|
||||
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">State</label>
|
||||
<ul class="w-48 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg dark:bg-gray-700 dark:border-gray-600 dark:text-white">
|
||||
<li class="w-full border-b border-gray-200 rounded-t-lg dark:border-gray-600">
|
||||
<div class="flex items-center ps-3">
|
||||
<input
|
||||
id="state-all"
|
||||
type="radio"
|
||||
value="all"
|
||||
name="state"
|
||||
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500"
|
||||
checked
|
||||
/>
|
||||
<label for="state-all" class="w-full py-3 ms-2 text-sm font-medium text-gray-900 dark:text-gray-300">All</label>
|
||||
</div>
|
||||
</li>
|
||||
<li class="w-full border-b border-gray-200 rounded-t-lg dark:border-gray-600">
|
||||
<div class="flex items-center ps-3">
|
||||
<input
|
||||
id="state-new"
|
||||
type="radio"
|
||||
value="new"
|
||||
name="state"
|
||||
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500"
|
||||
/>
|
||||
<label for="state-new" class="w-full py-3 ms-2 text-sm font-medium text-gray-900 dark:text-gray-300">New</label>
|
||||
</div>
|
||||
</li>
|
||||
<li class="w-full border-b border-gray-200 rounded-t-lg dark:border-gray-600">
|
||||
<div class="flex items-center ps-3">
|
||||
<input
|
||||
id="state-refurbished"
|
||||
type="radio"
|
||||
value="refurbished"
|
||||
name="state"
|
||||
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500"
|
||||
/>
|
||||
<label for="state-refurbished" class="w-full py-3 ms-2 text-sm font-medium text-gray-900 dark:text-gray-300">Refurbished</label>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div> -->
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex justify-between">
|
||||
<button
|
||||
type="button"
|
||||
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
|
||||
>
|
||||
Show 32 Results
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="py-2.5 px-5 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</app-dropdown>
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { Router, RouterModule } from '@angular/router';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { NavigationEnd, Router, RouterModule } from '@angular/router';
|
||||
import { faUserGear } from '@fortawesome/free-solid-svg-icons';
|
||||
import { Collapse, Dropdown, initFlowbite } from 'flowbite';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Observable, Subject, takeUntil } from 'rxjs';
|
||||
import { User } from '../../../../../bizmatch-server/src/models/db.model';
|
||||
import { emailToDirName, KeycloakUser } from '../../../../../bizmatch-server/src/models/main.model';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { SharedService } from '../../services/shared.service';
|
||||
import { UserService } from '../../services/user.service';
|
||||
import { map2User } from '../../utils/utils';
|
||||
import { DropdownComponent } from '../dropdown/dropdown.component';
|
||||
@Component({
|
||||
selector: 'header',
|
||||
standalone: true,
|
||||
imports: [CommonModule, RouterModule],
|
||||
imports: [CommonModule, RouterModule, DropdownComponent, FormsModule],
|
||||
templateUrl: './header.component.html',
|
||||
styleUrl: './header.component.scss',
|
||||
})
|
||||
@@ -27,23 +30,50 @@ export class HeaderComponent {
|
||||
faUserGear = faUserGear;
|
||||
profileUrl: string;
|
||||
env = environment;
|
||||
constructor(public keycloakService: KeycloakService, private router: Router, private userService: UserService, private sharedService: SharedService) {}
|
||||
private filterDropdown: Dropdown | null = null;
|
||||
isMobile: boolean = false;
|
||||
private destroy$ = new Subject<void>();
|
||||
prompt: string;
|
||||
constructor(public keycloakService: KeycloakService, private router: Router, private userService: UserService, private sharedService: SharedService, private breakpointObserver: BreakpointObserver) {}
|
||||
|
||||
async ngOnInit() {
|
||||
const token = await this.keycloakService.getToken();
|
||||
this.keycloakUser = map2User(token);
|
||||
this.user = await this.userService.getByMail(this.keycloakUser.email);
|
||||
this.profileUrl = this.user.hasProfile ? `${this.env.imageBaseUrl}/pictures/profile/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}` : `/assets/images/placeholder.png`;
|
||||
setTimeout(() => {
|
||||
initFlowbite();
|
||||
if (this.keycloakUser) {
|
||||
this.user = await this.userService.getByMail(this.keycloakUser?.email);
|
||||
this.profileUrl = this.user.hasProfile ? `${this.env.imageBaseUrl}/pictures/profile/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}` : `/assets/images/placeholder.png`;
|
||||
}
|
||||
|
||||
// setTimeout(() => {
|
||||
// initFlowbite();
|
||||
// });
|
||||
this.router.events.subscribe(event => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
initFlowbite();
|
||||
}
|
||||
});
|
||||
this.breakpointObserver
|
||||
.observe([Breakpoints.Handset])
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe(result => {
|
||||
this.isMobile = result.matches;
|
||||
const targetEl = document.getElementById('filterDropdown');
|
||||
const triggerEl = this.isMobile ? document.getElementById('filterDropdownMobileButton') : document.getElementById('filterDropdownButton');
|
||||
if (targetEl && triggerEl) {
|
||||
this.filterDropdown = new Dropdown(targetEl, triggerEl);
|
||||
}
|
||||
});
|
||||
this.sharedService.currentProfilePhoto.subscribe(photoUrl => {
|
||||
if (photoUrl) {
|
||||
this.profileUrl = photoUrl;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleFilterDropdown() {
|
||||
if (this.filterDropdown) {
|
||||
this.filterDropdown.toggle();
|
||||
}
|
||||
}
|
||||
ngAfterViewInit() {}
|
||||
|
||||
navigateWithState(dest: string, state: any) {
|
||||
@@ -82,4 +112,9 @@ export class HeaderComponent {
|
||||
this.closeDropdown();
|
||||
this.closeMobileMenu();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user