showInDirectory, loggingInterceptor, conditional Views props & profs
This commit is contained in:
parent
d8c48bf58a
commit
e37613ffa0
|
|
@ -33,6 +33,7 @@ export const users = pgTable(
|
||||||
subscriptionId: text('subscriptionId'),
|
subscriptionId: text('subscriptionId'),
|
||||||
subscriptionPlan: subscriptionTypeEnum('subscriptionPlan'),
|
subscriptionPlan: subscriptionTypeEnum('subscriptionPlan'),
|
||||||
location: jsonb('location'),
|
location: jsonb('location'),
|
||||||
|
showInDirectory: boolean('showInDirectory').default(true),
|
||||||
// city: varchar('city', { length: 255 }),
|
// city: varchar('city', { length: 255 }),
|
||||||
// state: char('state', { length: 2 }),
|
// state: char('state', { length: 2 }),
|
||||||
// latitude: doublePrecision('latitude'),
|
// latitude: doublePrecision('latitude'),
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export class LoggingInterceptor implements NestInterceptor {
|
||||||
|
|
||||||
const ip = this.cls.get('ip') || 'unknown';
|
const ip = this.cls.get('ip') || 'unknown';
|
||||||
const countryCode = this.cls.get('countryCode') || 'unknown';
|
const countryCode = this.cls.get('countryCode') || 'unknown';
|
||||||
const username = this.cls.get('username') || 'unknown';
|
const username = this.cls.get('email') || 'unknown';
|
||||||
|
|
||||||
const method = request.method;
|
const method = request.method;
|
||||||
const url = request.originalUrl;
|
const url = request.originalUrl;
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,12 @@ export class UserInterceptor implements NestInterceptor {
|
||||||
const request = context.switchToHttp().getRequest();
|
const request = context.switchToHttp().getRequest();
|
||||||
|
|
||||||
// Überprüfe, ob der Benutzer authentifiziert ist
|
// Überprüfe, ob der Benutzer authentifiziert ist
|
||||||
if (request.user && request.user.username) {
|
if (request.user && request.user.email) {
|
||||||
try {
|
try {
|
||||||
this.cls.set('username', request.user.username);
|
this.cls.set('email', request.user.email);
|
||||||
this.logger.log(`CLS context gesetzt: Username=${request.user.username}`);
|
this.logger.log(`CLS context gesetzt: EMail=${request.user.email}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error('Fehler beim Setzen der Username im CLS-Kontext', error);
|
this.logger.error('Fehler beim Setzen der EMail im CLS-Kontext', error);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.logger.log('Kein authentifizierter Benutzer gefunden');
|
this.logger.log('Kein authentifizierter Benutzer gefunden');
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,7 @@ export const UserSchema = z
|
||||||
updated: z.date().optional().nullable(),
|
updated: z.date().optional().nullable(),
|
||||||
subscriptionId: z.string().optional().nullable(),
|
subscriptionId: z.string().optional().nullable(),
|
||||||
subscriptionPlan: SubscriptionTypeEnum.optional().nullable(),
|
subscriptionPlan: SubscriptionTypeEnum.optional().nullable(),
|
||||||
|
showInDirectory: z.boolean(),
|
||||||
})
|
})
|
||||||
.superRefine((data, ctx) => {
|
.superRefine((data, ctx) => {
|
||||||
if (data.customerType === 'professional') {
|
if (data.customerType === 'professional') {
|
||||||
|
|
@ -233,7 +234,7 @@ export const UserSchema = z
|
||||||
ctx.addIssue({
|
ctx.addIssue({
|
||||||
code: z.ZodIssueCode.custom,
|
code: z.ZodIssueCode.custom,
|
||||||
message: 'Company location is required for professional customers',
|
message: 'Company location is required for professional customers',
|
||||||
path: ['companyLocation'],
|
path: ['location'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,10 @@ export class UserService {
|
||||||
if (criteria.state) {
|
if (criteria.state) {
|
||||||
whereConditions.push(sql`EXISTS (SELECT 1 FROM jsonb_array_elements(${schema.users.areasServed}) AS area WHERE area->>'state' = ${criteria.state})`);
|
whereConditions.push(sql`EXISTS (SELECT 1 FROM jsonb_array_elements(${schema.users.areasServed}) AS area WHERE area->>'state' = ${criteria.state})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//never show user which denied
|
||||||
|
whereConditions.push(eq(schema.users.showInDirectory, true))
|
||||||
|
|
||||||
return whereConditions;
|
return whereConditions;
|
||||||
}
|
}
|
||||||
async searchUserListings(criteria: UserListingCriteria): Promise<{ results: User[]; totalCount: number }> {
|
async searchUserListings(criteria: UserListingCriteria): Promise<{ results: User[]; totalCount: number }> {
|
||||||
|
|
@ -59,7 +63,7 @@ export class UserService {
|
||||||
const length = criteria.length ? criteria.length : 12;
|
const length = criteria.length ? criteria.length : 12;
|
||||||
const query = this.conn.select().from(schema.users);
|
const query = this.conn.select().from(schema.users);
|
||||||
const whereConditions = this.getWhereConditions(criteria);
|
const whereConditions = this.getWhereConditions(criteria);
|
||||||
|
|
||||||
if (whereConditions.length > 0) {
|
if (whereConditions.length > 0) {
|
||||||
const whereClause = and(...whereConditions);
|
const whereClause = and(...whereConditions);
|
||||||
query.where(whereClause);
|
query.where(whereClause);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<!-- <div class="container"> -->
|
<!-- <div class="container"> -->
|
||||||
<div class="wrapper" [ngClass]="{ 'bg-slate-100 print:bg-white': actualRoute !== 'home' }">
|
<div class="wrapper" [ngClass]="{ 'print:bg-white': actualRoute !== 'home' }">
|
||||||
@if (actualRoute !=='home' && actualRoute !=='login' && actualRoute!=='emailVerification' && actualRoute!=='email-authorized'){
|
@if (actualRoute !=='home' && actualRoute !=='login' && actualRoute!=='emailVerification' && actualRoute!=='email-authorized'){
|
||||||
<header></header>
|
<header></header>
|
||||||
}
|
}
|
||||||
<main class="flex-1">
|
<main class="flex-1 bg-slate-100">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@
|
||||||
>Businesses</a
|
>Businesses</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
@if ((numberOfCommercial$ | async) > 0) {
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
routerLink="/commercialPropertyListings"
|
routerLink="/commercialPropertyListings"
|
||||||
|
|
@ -120,6 +121,8 @@
|
||||||
>Properties</a
|
>Properties</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
}
|
||||||
|
@if ((numberOfBroker$ | async) > 0) {
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
routerLink="/brokerListings"
|
routerLink="/brokerListings"
|
||||||
|
|
@ -129,6 +132,7 @@
|
||||||
>Professionals</a
|
>Professionals</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
|
|
@ -151,6 +155,7 @@
|
||||||
>Businesses</a
|
>Businesses</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
@if ((numberOfCommercial$ | async) > 0) {
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
routerLink="/commercialPropertyListings"
|
routerLink="/commercialPropertyListings"
|
||||||
|
|
@ -160,6 +165,8 @@
|
||||||
>Properties</a
|
>Properties</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
}
|
||||||
|
@if ((numberOfBroker$ | async) > 0) {
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
routerLink="/brokerListings"
|
routerLink="/brokerListings"
|
||||||
|
|
@ -169,6 +176,7 @@
|
||||||
>Professionals</a
|
>Professionals</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
@ -200,6 +208,7 @@
|
||||||
>Businesses</a
|
>Businesses</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
@if ((numberOfCommercial$ | async) > 0) {
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
routerLinkActive="active-link"
|
routerLinkActive="active-link"
|
||||||
|
|
@ -210,6 +219,8 @@
|
||||||
>Properties</a
|
>Properties</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
}
|
||||||
|
@if ((numberOfBroker$ | async) > 0) {
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
routerLinkActive="active-link"
|
routerLinkActive="active-link"
|
||||||
|
|
@ -220,6 +231,7 @@
|
||||||
>Professionals</a
|
>Professionals</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import { BusinessListingCriteria, CommercialPropertyListingCriteria, emailToDirN
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { AuthService } from '../../services/auth.service';
|
import { AuthService } from '../../services/auth.service';
|
||||||
import { CriteriaChangeService } from '../../services/criteria-change.service';
|
import { CriteriaChangeService } from '../../services/criteria-change.service';
|
||||||
|
import { ListingsService } from '../../services/listings.service';
|
||||||
import { SearchService } from '../../services/search.service';
|
import { SearchService } from '../../services/search.service';
|
||||||
import { SelectOptionsService } from '../../services/select-options.service';
|
import { SelectOptionsService } from '../../services/select-options.service';
|
||||||
import { SharedService } from '../../services/shared.service';
|
import { SharedService } from '../../services/shared.service';
|
||||||
|
|
@ -46,6 +47,8 @@ export class HeaderComponent {
|
||||||
baseRoute: string;
|
baseRoute: string;
|
||||||
sortDropdownVisible: boolean;
|
sortDropdownVisible: boolean;
|
||||||
sortByOptions: KeyValueAsSortBy[] = [];
|
sortByOptions: KeyValueAsSortBy[] = [];
|
||||||
|
numberOfBroker$: Observable<number>;
|
||||||
|
numberOfCommercial$: Observable<number>;
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private userService: UserService,
|
private userService: UserService,
|
||||||
|
|
@ -56,6 +59,7 @@ export class HeaderComponent {
|
||||||
private criteriaChangeService: CriteriaChangeService,
|
private criteriaChangeService: CriteriaChangeService,
|
||||||
public selectOptions: SelectOptionsService,
|
public selectOptions: SelectOptionsService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
|
private listingService: ListingsService,
|
||||||
) {}
|
) {}
|
||||||
@HostListener('document:click', ['$event'])
|
@HostListener('document:click', ['$event'])
|
||||||
handleGlobalClick(event: Event) {
|
handleGlobalClick(event: Event) {
|
||||||
|
|
@ -71,7 +75,8 @@ export class HeaderComponent {
|
||||||
this.user = await this.userService.getByMail(this.keycloakUser?.email);
|
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`;
|
this.profileUrl = this.user.hasProfile ? `${this.env.imageBaseUrl}/pictures/profile/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}` : `/assets/images/placeholder.png`;
|
||||||
}
|
}
|
||||||
|
this.numberOfBroker$ = this.userService.getNumberOfBroker(createEmptyUserListingCriteria());
|
||||||
|
this.numberOfCommercial$ = this.listingService.getNumberOfListings(createEmptyCommercialPropertyListingCriteria(), 'commercialProperty');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
}, 10);
|
}, 10);
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@
|
||||||
>Businesses</a
|
>Businesses</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
@if ((numberOfCommercial$ | async) > 0) {
|
||||||
<li class="me-2">
|
<li class="me-2">
|
||||||
<a
|
<a
|
||||||
(click)="changeTab('commercialProperty')"
|
(click)="changeTab('commercialProperty')"
|
||||||
|
|
@ -68,6 +69,8 @@
|
||||||
>Properties</a
|
>Properties</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
}
|
||||||
|
@if ((numberOfBroker$ | async) > 0) {
|
||||||
<li class="me-2">
|
<li class="me-2">
|
||||||
<a
|
<a
|
||||||
(click)="changeTab('broker')"
|
(click)="changeTab('broker')"
|
||||||
|
|
@ -80,6 +83,7 @@
|
||||||
>Professionals</a
|
>Professionals</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
} @if(aiSearch){
|
} @if(aiSearch){
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,8 @@ export class HomeComponent {
|
||||||
cityOrState = undefined;
|
cityOrState = undefined;
|
||||||
private criteriaChangeSubscription: Subscription;
|
private criteriaChangeSubscription: Subscription;
|
||||||
numberOfResults$: Observable<number>;
|
numberOfResults$: Observable<number>;
|
||||||
|
numberOfBroker$: Observable<number>;
|
||||||
|
numberOfCommercial$: Observable<number>;
|
||||||
aiSearch = false;
|
aiSearch = false;
|
||||||
aiSearchText = '';
|
aiSearchText = '';
|
||||||
aiSearchFailed = false;
|
aiSearchFailed = false;
|
||||||
|
|
@ -84,7 +85,8 @@ export class HomeComponent {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
}, 0);
|
}, 0);
|
||||||
|
this.numberOfBroker$ = this.userService.getNumberOfBroker(createEmptyUserListingCriteria());
|
||||||
|
this.numberOfCommercial$ = this.listingService.getNumberOfListings(createEmptyCommercialPropertyListingCriteria(), 'commercialProperty');
|
||||||
const token = await this.authService.getToken();
|
const token = await this.authService.getToken();
|
||||||
sessionStorage.removeItem('businessListings');
|
sessionStorage.removeItem('businessListings');
|
||||||
sessionStorage.removeItem('commercialPropertyListings');
|
sessionStorage.removeItem('commercialPropertyListings');
|
||||||
|
|
@ -114,14 +116,7 @@ export class HomeComponent {
|
||||||
private setupCriteriaChangeListener() {
|
private setupCriteriaChangeListener() {
|
||||||
this.criteriaChangeSubscription = this.criteriaChangeService.criteriaChange$.pipe(untilDestroyed(this), debounceTime(400)).subscribe(() => this.setTotalNumberOfResults());
|
this.criteriaChangeSubscription = this.criteriaChangeService.criteriaChange$.pipe(untilDestroyed(this), debounceTime(400)).subscribe(() => this.setTotalNumberOfResults());
|
||||||
}
|
}
|
||||||
// login() {
|
|
||||||
// this.keycloakService.login({
|
|
||||||
// redirectUri: `${window.location.origin}/login${this.router.routerState.snapshot.url}`,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// register() {
|
|
||||||
// this.keycloakService.register({ redirectUri: `${window.location.origin}/account` });
|
|
||||||
// }
|
|
||||||
toggleMenu() {
|
toggleMenu() {
|
||||||
this.isMenuOpen = !this.isMenuOpen;
|
this.isMenuOpen = !this.isMenuOpen;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -220,6 +220,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
<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" />
|
||||||
|
<div class="toggle-bg block w-12 h-6 rounded-full bg-gray-600 transition"></div>
|
||||||
|
</div>
|
||||||
|
<div class="ml-3 text-gray-700 font-medium">Show your profile in Professional Directory</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-start">
|
<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)">
|
<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)">
|
||||||
Update Profile
|
Update Profile
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue