parent
923040f487
commit
715fbdf2f5
|
|
@ -73,14 +73,6 @@ export const businesses = pgTable(
|
||||||
created: timestamp('created'),
|
created: timestamp('created'),
|
||||||
updated: timestamp('updated'),
|
updated: timestamp('updated'),
|
||||||
location: jsonb('location'),
|
location: jsonb('location'),
|
||||||
// city: varchar('city', { length: 255 }),
|
|
||||||
// state: char('state', { length: 2 }),
|
|
||||||
// zipCode: integer('zipCode'),
|
|
||||||
// county: varchar('county', { length: 255 }),
|
|
||||||
// street: varchar('street', { length: 255 }),
|
|
||||||
// housenumber: varchar('housenumber', { length: 10 }),
|
|
||||||
// latitude: doublePrecision('latitude'),
|
|
||||||
// longitude: doublePrecision('longitude'),
|
|
||||||
},
|
},
|
||||||
table => ({
|
table => ({
|
||||||
locationBusinessCityStateIdx: index('idx_business_location_city_state').on(
|
locationBusinessCityStateIdx: index('idx_business_location_city_state').on(
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
import { BadRequestException, Inject, Injectable, NotFoundException } from '@nestjs/common';
|
||||||
import { and, arrayContains, asc, count, desc, eq, gte, ilike, inArray, lte, ne, or, SQL, sql } from 'drizzle-orm';
|
import { and, arrayContains, asc, count, desc, eq, gte, ilike, inArray, lte, ne, or, SQL, sql } from 'drizzle-orm';
|
||||||
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
||||||
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
||||||
|
|
@ -246,10 +246,18 @@ export class BusinessListingService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #### UPDATE Business ########################################
|
// #### UPDATE Business ########################################
|
||||||
async updateBusinessListing(id: string, data: BusinessListing): Promise<BusinessListing> {
|
async updateBusinessListing(id: string, data: BusinessListing, user: JwtUser): Promise<BusinessListing> {
|
||||||
try {
|
try {
|
||||||
|
const [existingListing] = await this.conn.select().from(businesses).where(eq(businesses.id, id));
|
||||||
|
|
||||||
|
if (!existingListing) {
|
||||||
|
throw new NotFoundException(`Business listing with id ${id} not found`);
|
||||||
|
}
|
||||||
data.updated = new Date();
|
data.updated = new Date();
|
||||||
data.created = data.created ? (typeof data.created === 'string' ? new Date(data.created) : data.created) : new Date();
|
data.created = data.created ? (typeof data.created === 'string' ? new Date(data.created) : data.created) : new Date();
|
||||||
|
if (existingListing.email === user?.email) {
|
||||||
|
data.favoritesForUser = existingListing.favoritesForUser;
|
||||||
|
}
|
||||||
BusinessListingSchema.parse(data);
|
BusinessListingSchema.parse(data);
|
||||||
const convertedBusinessListing = data;
|
const convertedBusinessListing = data;
|
||||||
const [updateListing] = await this.conn.update(businesses).set(convertedBusinessListing).where(eq(businesses.id, id)).returning();
|
const [updateListing] = await this.conn.update(businesses).set(convertedBusinessListing).where(eq(businesses.id, id)).returning();
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,8 @@ export class BusinessListingsController {
|
||||||
|
|
||||||
@UseGuards(OptionalAuthGuard)
|
@UseGuards(OptionalAuthGuard)
|
||||||
@Put()
|
@Put()
|
||||||
async update(@Body() listing: any) {
|
async update(@Request() req, @Body() listing: any) {
|
||||||
return await this.listingsService.updateBusinessListing(listing.id, listing);
|
return await this.listingsService.updateBusinessListing(listing.id, listing, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(OptionalAuthGuard)
|
@UseGuards(OptionalAuthGuard)
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,8 @@ export class CommercialPropertyListingsController {
|
||||||
|
|
||||||
@UseGuards(OptionalAuthGuard)
|
@UseGuards(OptionalAuthGuard)
|
||||||
@Put()
|
@Put()
|
||||||
async update(@Body() listing: any) {
|
async update(@Request() req, @Body() listing: any) {
|
||||||
return await this.listingsService.updateCommercialPropertyListing(listing.id, listing);
|
return await this.listingsService.updateCommercialPropertyListing(listing.id, listing, req.user as JwtUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(OptionalAuthGuard)
|
@UseGuards(OptionalAuthGuard)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
import { BadRequestException, Inject, Injectable, NotFoundException } from '@nestjs/common';
|
||||||
import { and, arrayContains, asc, count, desc, eq, gte, ilike, inArray, lte, ne, or, SQL, sql } from 'drizzle-orm';
|
import { and, arrayContains, asc, count, desc, eq, gte, ilike, inArray, lte, ne, or, SQL, sql } from 'drizzle-orm';
|
||||||
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
||||||
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
||||||
|
|
@ -181,10 +181,18 @@ export class CommercialPropertyService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #### UPDATE CommercialProps ########################################
|
// #### UPDATE CommercialProps ########################################
|
||||||
async updateCommercialPropertyListing(id: string, data: CommercialPropertyListing): Promise<CommercialPropertyListing> {
|
async updateCommercialPropertyListing(id: string, data: CommercialPropertyListing, user: JwtUser): Promise<CommercialPropertyListing> {
|
||||||
try {
|
try {
|
||||||
|
const [existingListing] = await this.conn.select().from(commercials).where(eq(commercials.id, id));
|
||||||
|
|
||||||
|
if (!existingListing) {
|
||||||
|
throw new NotFoundException(`Business listing with id ${id} not found`);
|
||||||
|
}
|
||||||
data.updated = new Date();
|
data.updated = new Date();
|
||||||
data.created = data.created ? (typeof data.created === 'string' ? new Date(data.created) : data.created) : new Date();
|
data.created = data.created ? (typeof data.created === 'string' ? new Date(data.created) : data.created) : new Date();
|
||||||
|
if (existingListing.email === user?.email || !user) {
|
||||||
|
data.favoritesForUser = existingListing.favoritesForUser;
|
||||||
|
}
|
||||||
CommercialPropertyListingSchema.parse(data);
|
CommercialPropertyListingSchema.parse(data);
|
||||||
const imageOrder = await this.fileService.getPropertyImages(data.imagePath, String(data.serialId));
|
const imageOrder = await this.fileService.getPropertyImages(data.imagePath, String(data.serialId));
|
||||||
const difference = imageOrder.filter(x => !data.imageOrder.includes(x)).concat(data.imageOrder.filter(x => !imageOrder.includes(x)));
|
const difference = imageOrder.filter(x => !data.imageOrder.includes(x)).concat(data.imageOrder.filter(x => !imageOrder.includes(x)));
|
||||||
|
|
@ -216,13 +224,13 @@ export class CommercialPropertyService {
|
||||||
const index = listing.imageOrder.findIndex(im => im === name);
|
const index = listing.imageOrder.findIndex(im => im === name);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
listing.imageOrder.splice(index, 1);
|
listing.imageOrder.splice(index, 1);
|
||||||
await this.updateCommercialPropertyListing(listing.id, listing);
|
await this.updateCommercialPropertyListing(listing.id, listing, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async addImage(imagePath: string, serial: string, imagename: string) {
|
async addImage(imagePath: string, serial: string, imagename: string) {
|
||||||
const listing = (await this.findByImagePath(imagePath, serial)) as unknown as CommercialPropertyListing;
|
const listing = (await this.findByImagePath(imagePath, serial)) as unknown as CommercialPropertyListing;
|
||||||
listing.imageOrder.push(imagename);
|
listing.imageOrder.push(imagename);
|
||||||
await this.updateCommercialPropertyListing(listing.id, listing);
|
await this.updateCommercialPropertyListing(listing.id, listing, null);
|
||||||
}
|
}
|
||||||
// #### DELETE ########################################
|
// #### DELETE ########################################
|
||||||
async deleteListing(id: string): Promise<void> {
|
async deleteListing(id: string): Promise<void> {
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
data-dropdown-placement="bottom"
|
data-dropdown-placement="bottom"
|
||||||
>
|
>
|
||||||
<span class="sr-only">Open user menu</span>
|
<span class="sr-only">Open user menu</span>
|
||||||
@if(user?.hasProfile){
|
@if(isProfessional || (authService.isAdmin() | async) && user?.hasProfile){
|
||||||
<img class="w-8 h-8 rounded-full object-cover" src="{{ profileUrl }}" alt="user photo" />
|
<img class="w-8 h-8 rounded-full object-cover" src="{{ profileUrl }}" alt="user photo" />
|
||||||
} @else {
|
} @else {
|
||||||
<i class="flex justify-center items-center text-stone-50 w-8 h-8 rounded-full fa-solid fa-bars"></i>
|
<i class="flex justify-center items-center text-stone-50 w-8 h-8 rounded-full fa-solid fa-bars"></i>
|
||||||
|
|
|
||||||
|
|
@ -200,4 +200,7 @@ export class HeaderComponent {
|
||||||
toggleSortDropdown() {
|
toggleSortDropdown() {
|
||||||
this.sortDropdownVisible = !this.sortDropdownVisible;
|
this.sortDropdownVisible = !this.sortDropdownVisible;
|
||||||
}
|
}
|
||||||
|
get isProfessional() {
|
||||||
|
return this.user?.customerType === 'professional';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@ export class DetailsBusinessListingComponent extends BaseDetailsComponent {
|
||||||
this.mailinfo.email = this.listingUser.email;
|
this.mailinfo.email = this.listingUser.email;
|
||||||
this.mailinfo.listing = this.listing;
|
this.mailinfo.listing = this.listing;
|
||||||
await this.mailService.mail(this.mailinfo);
|
await this.mailService.mail(this.mailinfo);
|
||||||
|
this.validationMessagesService.clearMessages();
|
||||||
this.auditService.createEvent(this.listing.id, 'contact', this.user?.email, this.mailinfo.sender);
|
this.auditService.createEvent(this.listing.id, 'contact', this.user?.email, this.mailinfo.sender);
|
||||||
this.messageService.addMessage({ severity: 'success', text: 'Your message has been sent to the creator of the listing', duration: 3000 });
|
this.messageService.addMessage({ severity: 'success', text: 'Your message has been sent to the creator of the listing', duration: 3000 });
|
||||||
this.mailinfo = createMailInfo(this.user);
|
this.mailinfo = createMailInfo(this.user);
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,7 @@ export class DetailsCommercialPropertyListingComponent extends BaseDetailsCompon
|
||||||
this.mailinfo.email = this.listingUser.email;
|
this.mailinfo.email = this.listingUser.email;
|
||||||
this.mailinfo.listing = this.listing;
|
this.mailinfo.listing = this.listing;
|
||||||
await this.mailService.mail(this.mailinfo);
|
await this.mailService.mail(this.mailinfo);
|
||||||
|
this.validationMessagesService.clearMessages();
|
||||||
this.auditService.createEvent(this.listing.id, 'contact', this.user?.email, this.mailinfo.sender);
|
this.auditService.createEvent(this.listing.id, 'contact', this.user?.email, this.mailinfo.sender);
|
||||||
this.messageService.addMessage({ severity: 'success', text: 'Your message has been sent to the creator of the listing', duration: 3000 });
|
this.messageService.addMessage({ severity: 'success', text: 'Your message has been sent to the creator of the listing', duration: 3000 });
|
||||||
this.mailinfo = createMailInfo(this.user);
|
this.mailinfo = createMailInfo(this.user);
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,8 @@ export class AuthService {
|
||||||
// Cache zurücksetzen, wenn die Caching-Zeit abgelaufen ist oder kein Cache existiert
|
// Cache zurücksetzen, wenn die Caching-Zeit abgelaufen ist oder kein Cache existiert
|
||||||
if (!this.cachedUserRole$ || now - this.lastCacheTime > this.cacheDuration) {
|
if (!this.cachedUserRole$ || now - this.lastCacheTime > this.cacheDuration) {
|
||||||
this.lastCacheTime = now;
|
this.lastCacheTime = now;
|
||||||
this.cachedUserRole$ = this.http.get<{ role: UserRole | null }>(`${environment.apiBaseUrl}/bizmatch/auth/me/role`).pipe(
|
let headers = new HttpHeaders().set('X-Hide-Loading', 'true').set('Accept-Language', 'en-US');
|
||||||
|
this.cachedUserRole$ = this.http.get<{ role: UserRole | null }>(`${environment.apiBaseUrl}/bizmatch/auth/me/role`, { headers }).pipe(
|
||||||
map(response => response.role),
|
map(response => response.role),
|
||||||
tap(role => this.userRoleSubject.next(role)),
|
tap(role => this.userRoleSubject.next(role)),
|
||||||
catchError(error => {
|
catchError(error => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue