diff --git a/bizmatch-server/src/ai/ai.service.ts b/bizmatch-server/src/ai/ai.service.ts
index ade9f75..1c0dd14 100644
--- a/bizmatch-server/src/ai/ai.service.ts
+++ b/bizmatch-server/src/ai/ai.service.ts
@@ -3,30 +3,85 @@ import Groq from 'groq-sdk';
import OpenAI from 'openai';
import { BusinessListingCriteria } from '../models/main.model';
-const businessListingCriteriaStructure = {
- criteriaType: 'business | commercialProperty | broker',
- types: "'Automotive'|'Industrial Services'|'Food and Restaurant'|'Real Estate'|'Retail'|'Oilfield SVE and MFG.'|'Service'|'Advertising'|'Agriculture'|'Franchise'|'Professional'|'Manufacturing'",
- city: 'string',
- state: 'string',
- county: 'string',
- minPrice: 'number',
- maxPrice: 'number',
- minRevenue: 'number',
- maxRevenue: 'number',
- minCashFlow: 'number',
- maxCashFlow: 'number',
- minNumberEmployees: 'number',
- maxNumberEmployees: 'number',
- establishedSince: 'number',
- establishedUntil: 'number',
- realEstateChecked: 'boolean',
- leasedLocation: 'boolean',
- franchiseResale: 'boolean',
- title: 'string',
- brokerName: 'string',
- searchType: "'exact' | 'radius'",
- radius: "'0' | '5' | '20' | '50' | '100' | '200' | '300' | '400' | '500'",
-};
+// const businessListingCriteriaStructure = {
+// criteriaType: 'business | commercialProperty | broker',
+// types: "'Automotive'|'Industrial Services'|'Food and Restaurant'|'Real Estate'|'Retail'|'Oilfield SVE and MFG.'|'Service'|'Advertising'|'Agriculture'|'Franchise'|'Professional'|'Manufacturing'",
+// city: 'string',
+// state: 'string',
+// county: 'string',
+// minPrice: 'number',
+// maxPrice: 'number',
+// minRevenue: 'number',
+// maxRevenue: 'number',
+// minCashFlow: 'number',
+// maxCashFlow: 'number',
+// minNumberEmployees: 'number',
+// maxNumberEmployees: 'number',
+// establishedSince: 'number',
+// establishedUntil: 'number',
+// realEstateChecked: 'boolean',
+// leasedLocation: 'boolean',
+// franchiseResale: 'boolean',
+// title: 'string',
+// brokerName: 'string',
+// searchType: "'exact' | 'radius'",
+// radius: "'0' | '5' | '20' | '50' | '100' | '200' | '300' | '400' | '500'",
+// };
+
+const BusinessListingCriteriaStructure = `
+export interface BusinessListingCriteria {
+ state: string;
+ city: string;
+ searchType: 'exact' | 'radius';
+ radius: '20' | '50' | '100' | '200' | '300' | '400' | '500';
+
+ minPrice: number;
+ maxPrice: number;
+ minRevenue: number;
+ maxRevenue: number;
+ minCashFlow: number;
+ maxCashFlow: number;
+ minNumberEmployees: number;
+ maxNumberEmployees: number;
+ establishedSince: number;
+ establishedUntil: number;
+ realEstateChecked: boolean;
+ leasedLocation: boolean;
+ franchiseResale: boolean;
+ //title: string;
+ brokerName: string;
+ //types:"'Automotive'|'Industrial Services'|'Food and Restaurant'|'Real Estate'|'Retail'|'Oilfield SVE and MFG.'|'Service'|'Advertising'|'Agriculture'|'Franchise'|'Professional'|'Manufacturing'",
+ criteriaType: 'businessListings';
+}
+`;
+const CommercialPropertyListingCriteriaStructure = `
+export interface CommercialPropertyListingCriteria {
+ state: string;
+ city: string;
+ searchType: 'exact' | 'radius';
+ radius: '20' | '50' | '100' | '200' | '300' | '400' | '500';
+
+ minPrice: number;
+ maxPrice: number;
+ //title: string;
+ //types:"'Retail'|'Land'|'Industrial'|'Office'|'Mixed Use'|'Multifamily'|'Uncategorized'"
+ criteriaType: 'commercialPropertyListings';
+}
+`;
+const UserListingCriteriaStructure = `
+export interface UserListingCriteria {
+ state: string;
+ city: string;
+ searchType: 'exact' | 'radius';
+ radius: '20' | '50' | '100' | '200' | '300' | '400' | '500';
+
+ brokerName: string;
+ companyName: string;
+ counties: string[];
+ criteriaType: 'brokerListings';
+}
+
+`;
@Injectable()
export class AiService {
private readonly openai: OpenAI;
@@ -67,8 +122,10 @@ export class AiService {
{
role: 'system',
content: `Please create unformatted JSON Object from a user input.
- The type must be: ${JSON.stringify(businessListingCriteriaStructure)}.
- If location details available please fill city and state as State Code and only county if explicitly mentioned`,
+ The criteriaType must be only either 'businessListings' or 'commercialPropertyListings' or 'brokerListings' !!!!
+ The format of the object (depending on your choice of criteriaType) must be either ${BusinessListingCriteriaStructure}, ${CommercialPropertyListingCriteriaStructure} or ${UserListingCriteriaStructure} !!!!
+ If location details available please fill city and state as State Code and only county if explicitly mentioned.
+ If you decide for searchType==='exact', please do not set the attribute radius`,
},
{
role: 'user',
diff --git a/bizmatch/src/app/components/header/header.component.ts b/bizmatch/src/app/components/header/header.component.ts
index b121ae2..39cd1a7 100644
--- a/bizmatch/src/app/components/header/header.component.ts
+++ b/bizmatch/src/app/components/header/header.component.ts
@@ -4,6 +4,7 @@ import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { NavigationEnd, Router, RouterModule } from '@angular/router';
import { faUserGear } from '@fortawesome/free-solid-svg-icons';
+import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { Collapse, Dropdown, initFlowbite } from 'flowbite';
import { KeycloakService } from 'keycloak-angular';
import { filter, Observable, Subject, Subscription } from 'rxjs';
@@ -17,6 +18,7 @@ import { UserService } from '../../services/user.service';
import { assignProperties, compareObjects, createEmptyBusinessListingCriteria, createEmptyCommercialPropertyListingCriteria, createEmptyUserListingCriteria, getCriteriaProxy, map2User } from '../../utils/utils';
import { DropdownComponent } from '../dropdown/dropdown.component';
import { ModalService } from '../search-modal/modal.service';
+@UntilDestroy()
@Component({
selector: 'header',
standalone: true,
@@ -75,6 +77,12 @@ export class HeaderComponent {
this.routerSubscription = this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe((event: any) => {
this.checkCurrentRoute(event.urlAfterRedirects);
});
+
+ this.userService.currentUser.pipe(untilDestroyed(this)).subscribe(u => {
+ if (u !== undefined) {
+ this.user = u;
+ }
+ });
}
private checkCurrentRoute(url: string): void {
this.baseRoute = url.split('/')[1]; // Nimmt den ersten Teil der Route nach dem ersten '/'
diff --git a/bizmatch/src/app/components/search-modal/search-modal.component.html b/bizmatch/src/app/components/search-modal/search-modal.component.html
index 96b86ad..fce32db 100644
--- a/bizmatch/src/app/components/search-modal/search-modal.component.html
+++ b/bizmatch/src/app/components/search-modal/search-modal.component.html
@@ -445,7 +445,7 @@
-
+
Find businesses for sale.
Unlocking Exclusive Opportunities - Empowering Entrepreneurial Dreams
-
+
+ @if(!aiSearch){
- @if(criteria){
+ } @if(aiSearch){
+
+
+
+
+
+
+ } @if(criteria && !aiSearch){
- @if (criteria.radius){
+ @if (criteria.radius && !aiSearch){
diff --git a/bizmatch/src/app/pages/home/home.component.scss b/bizmatch/src/app/pages/home/home.component.scss
index 7d4bd35..bec5f8e 100644
--- a/bizmatch/src/app/pages/home/home.component.scss
+++ b/bizmatch/src/app/pages/home/home.component.scss
@@ -28,10 +28,10 @@ select {
}
.toggle-checkbox:checked {
right: 0;
- border-color: #4fd1c5;
+ border-color: rgb(125 211 252);
}
.toggle-checkbox:checked + .toggle-label {
- background-color: #4fd1c5;
+ background-color: rgb(125 211 252);
}
:host ::ng-deep .ng-select.ng-select-single .ng-select-container {
height: 48px;
@@ -56,9 +56,19 @@ select option {
select.placeholder-selected {
color: #999; /* Farbe für den Platzhalter */
}
+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;
}
+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;
+}
diff --git a/bizmatch/src/app/pages/home/home.component.ts b/bizmatch/src/app/pages/home/home.component.ts
index ebaa21a..3732330 100644
--- a/bizmatch/src/app/pages/home/home.component.ts
+++ b/bizmatch/src/app/pages/home/home.component.ts
@@ -1,20 +1,30 @@
import { CommonModule } from '@angular/common';
-import { ChangeDetectorRef, Component } from '@angular/core';
+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 { KeycloakService } from 'keycloak-angular';
-import { catchError, concat, debounceTime, distinctUntilChanged, Observable, of, Subject, Subscription, switchMap, tap } from 'rxjs';
+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 { AiService } from '../../services/ai.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 { UserService } from '../../services/user.service';
-import { compareObjects, createEmptyBusinessListingCriteria, createEmptyCommercialPropertyListingCriteria, createEmptyUserListingCriteria, createEnhancedProxy, getCriteriaStateObject, map2User } from '../../utils/utils';
+import {
+ assignProperties,
+ compareObjects,
+ createEmptyBusinessListingCriteria,
+ createEmptyCommercialPropertyListingCriteria,
+ createEmptyUserListingCriteria,
+ createEnhancedProxy,
+ getCriteriaStateObject,
+ map2User,
+} from '../../utils/utils';
@UntilDestroy()
@Component({
selector: 'app-home',
@@ -24,6 +34,7 @@ import { compareObjects, createEmptyBusinessListingCriteria, createEmptyCommerci
styleUrl: './home.component.scss',
})
export class HomeComponent {
+ placeholders: string[] = ['waterfront property close to Houston less than 1M', 'construction area with beach access close to San Diego'];
activeTabAction: 'business' | 'commercialProperty' | 'broker' = 'business';
type: string;
maxPrice: string;
@@ -39,6 +50,18 @@ export class HomeComponent {
cityOrState = undefined;
private criteriaChangeSubscription: Subscription;
numberOfResults$: Observable
;
+
+ aiSearch = false;
+ aiSearchText = '';
+ 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
+
public constructor(
private router: Router,
private modalService: ModalService,
@@ -51,6 +74,7 @@ export class HomeComponent {
public cdRef: ChangeDetectorRef,
private listingService: ListingsService,
private userService: UserService,
+ private aiService: AiService,
) {}
async ngOnInit() {
const token = await this.keycloakService.getToken();
@@ -193,4 +217,87 @@ export class HomeComponent {
return 0;
}
}
+ toggleAiSearch() {
+ this.aiSearch = !this.aiSearch;
+ 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;
+ const result = await this.aiService.generateAiReponse(this.aiSearchText);
+ console.log(result);
+ 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();
+ }
}
diff --git a/bizmatch/src/app/pages/pricing/pricing.component.ts b/bizmatch/src/app/pages/pricing/pricing.component.ts
index d1a2ae8..6e7b75d 100644
--- a/bizmatch/src/app/pages/pricing/pricing.component.ts
+++ b/bizmatch/src/app/pages/pricing/pricing.component.ts
@@ -28,13 +28,19 @@ export class PricingComponent {
async ngOnInit() {
const token = await this.keycloakService.getToken();
this.keycloakUser = map2User(token);
- if (this.id) {
- this.checkout({ priceId: atob(this.id), email: this.keycloakUser.email, name: `${this.keycloakUser.firstName} ${this.keycloakUser.lastName}` });
- }
- if (this.keycloakUser && !this.id) {
- this.user = await this.userService.getByMail(this.keycloakUser.email);
- if (this.user.subscriptionId) {
+ if (this.keycloakUser) {
+ if (this.id === 'free') {
+ this.user = await this.userService.getByMail(this.keycloakUser.email);
+ this.user.subscriptionPlan = 'free';
+ await this.userService.save(this.user);
this.router.navigate([`/account`]);
+ } else if (this.id) {
+ this.checkout({ priceId: atob(this.id), email: this.keycloakUser.email, name: `${this.keycloakUser.firstName} ${this.keycloakUser.lastName}` });
+ } else if (!this.id) {
+ this.user = await this.userService.getByMail(this.keycloakUser.email);
+ if (this.user.subscriptionId) {
+ this.router.navigate([`/account`]);
+ }
}
}
}
@@ -55,7 +61,7 @@ export class PricingComponent {
redirectUri: `${window.location.origin}/pricing/${btoa(priceId)}`,
});
} else {
- this.keycloakService.register({ redirectUri: `${window.location.origin}/account` });
+ this.keycloakService.register({ redirectUri: `${window.location.origin}/pricing/free` });
}
}
}
diff --git a/bizmatch/src/app/pages/subscription/account/account.component.ts b/bizmatch/src/app/pages/subscription/account/account.component.ts
index a6e9ad2..cb5be76 100644
--- a/bizmatch/src/app/pages/subscription/account/account.component.ts
+++ b/bizmatch/src/app/pages/subscription/account/account.component.ts
@@ -10,7 +10,7 @@ import { ImageCropperComponent } from 'ngx-image-cropper';
import { QuillModule } from 'ngx-quill';
import { lastValueFrom } from 'rxjs';
import { User } from '../../../../../../bizmatch-server/src/models/db.model';
-import { AutoCompleteCompleteEvent, Invoice, StripeSubscription, UploadParams, ValidationMessage, createDefaultUser, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
+import { AutoCompleteCompleteEvent, Invoice, StripeSubscription, UploadParams, ValidationMessage, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
import { environment } from '../../../../environments/environment';
import { ConfirmationComponent } from '../../../components/confirmation/confirmation.component';
import { ConfirmationService } from '../../../components/confirmation/confirmation.service';
@@ -111,10 +111,6 @@ export class AccountComponent {
this.subscriptions = await lastValueFrom(this.subscriptionService.getAllSubscriptions(this.user.email));
await this.synchronizeSubscriptions(this.subscriptions);
- // if (this.subscriptions.length === 0) {
- // this.subscriptions = [{ ended_at: null, start_date: Math.floor(new Date(this.user.created).getTime() / 1000), status: null, metadata: { plan: 'Free Plan' } }];
- // }
-
this.profileUrl = this.user.hasProfile ? `${this.env.imageBaseUrl}/pictures/profile/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}` : `/assets/images/placeholder.png`;
this.companyLogoUrl = this.user.hasCompanyLogo ? `${this.env.imageBaseUrl}/pictures/logo/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}` : `/assets/images/placeholder.png`;
@@ -168,22 +164,9 @@ export class AccountComponent {
printInvoice(invoice: Invoice) {}
async updateProfile(user: User) {
- if (this.user.customerType === 'buyer') {
- const confirmed = await this.confirmationService.showConfirmation({ message: 'Are you sure you want to switch to Buyer ? All your listings as well as all your professionals informations will be deleted' });
- if (confirmed) {
- const id = this.user.id;
- this.user = createDefaultUser(this.user.email, this.user.firstname, this.user.lastname, null);
- this.user.customerType = 'buyer';
- this.user.id = id;
- this.imageService.deleteLogoImagesByMail(this.user.email);
- this.imageService.deleteProfileImagesByMail(this.user.email);
- } else {
- this.user.customerType = 'professional';
- return;
- }
- }
try {
await this.userService.save(this.user);
+ this.userService.changeUser(this.user);
this.messageService.addMessage({ severity: 'success', text: 'Account changes have been persisted', duration: 3000 });
this.validationMessagesService.clearMessages(); // Löschen Sie alle bestehenden Validierungsnachrichten
this.validationMessages = [];
diff --git a/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.html b/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.html
index 7024ff8..11b8bd8 100644
--- a/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.html
+++ b/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.html
@@ -7,11 +7,12 @@
diff --git a/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.ts b/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.ts
index 2f8ef1f..eadff1e 100644
--- a/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.ts
+++ b/bizmatch/src/app/pages/subscription/edit-commercial-property-listing/edit-commercial-property-listing.component.ts
@@ -98,6 +98,7 @@ export class EditCommercialPropertyListingComponent {
data: BusinessListing;
userId: string;
typesOfCommercialProperty = [];
+ listingCategories = [];
env = environment;
ts = new Date().getTime();
quillModules = {
@@ -144,6 +145,13 @@ export class EditCommercialPropertyListingComponent {
async ngOnInit() {
const token = await this.keycloakService.getToken();
const keycloakUser = map2User(token);
+ const email = keycloakUser.email;
+ this.user = await this.userService.getByMail(email);
+ this.listingCategories = this.selectOptions.listingCategories
+ .filter(lc => lc.value === 'commercialProperty' || (this.user.customerSubType === 'broker' && lc.value === 'business'))
+ .map(e => {
+ return { name: e.name, value: e.value };
+ });
if (this.mode === 'edit') {
this.listing = (await lastValueFrom(this.listingsService.getListingById(this.id, 'commercialProperty'))) as CommercialPropertyListing;
} else {
diff --git a/bizmatch/src/app/services/ai.service.ts b/bizmatch/src/app/services/ai.service.ts
new file mode 100644
index 0000000..7ccca84
--- /dev/null
+++ b/bizmatch/src/app/services/ai.service.ts
@@ -0,0 +1,19 @@
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { lastValueFrom } from 'rxjs';
+import { BusinessListingCriteria, CommercialPropertyListingCriteria, UserListingCriteria } from '../../../../bizmatch-server/src/models/main.model';
+import { environment } from '../../environments/environment';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class AiService {
+ private apiBaseUrl = environment.apiBaseUrl;
+ constructor(private http: HttpClient) {}
+
+ async generateAiReponse(prompt: string): Promise {
+ let headers = new HttpHeaders();
+ headers = headers.set('X-Hide-Loading', 'true');
+ return lastValueFrom(this.http.post(`${this.apiBaseUrl}/bizmatch/ai`, { query: prompt }, { headers }));
+ }
+}
diff --git a/bizmatch/src/app/services/user.service.ts b/bizmatch/src/app/services/user.service.ts
index 3005f07..4bd2d60 100644
--- a/bizmatch/src/app/services/user.service.ts
+++ b/bizmatch/src/app/services/user.service.ts
@@ -1,6 +1,6 @@
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
-import { lastValueFrom, Observable } from 'rxjs';
+import { BehaviorSubject, lastValueFrom, Observable } from 'rxjs';
import urlcat from 'urlcat';
import { User } from '../../../../bizmatch-server/src/models/db.model';
import { ResponseUsersArray, StatesResult, UserListingCriteria } from '../../../../bizmatch-server/src/models/main.model';
@@ -12,8 +12,14 @@ import { environment } from '../../environments/environment';
export class UserService {
private apiBaseUrl = environment.apiBaseUrl;
+ private userSource = new BehaviorSubject(undefined);
+ currentUser = this.userSource.asObservable();
+
constructor(private http: HttpClient) {}
+ changeUser(user: User) {
+ this.userSource.next(user);
+ }
// -----------------------------
// DB services
// -----------------------------
diff --git a/bizmatch/src/styles.scss b/bizmatch/src/styles.scss
index c1621d6..e5c8d80 100644
--- a/bizmatch/src/styles.scss
+++ b/bizmatch/src/styles.scss
@@ -92,5 +92,5 @@ p-menubarsub ul {
}
input::placeholder,
textarea::placeholder {
- color: #cfd7e0 !important;
+ color: #999 !important;
}