This commit is contained in:
parent
ec0576e7b8
commit
1f8febc479
|
|
@ -21,7 +21,7 @@ export class BusinessListingService {
|
|||
private geoService?: GeoService,
|
||||
) {}
|
||||
|
||||
private getWhereConditions(criteria: BusinessListingCriteria): SQL[] {
|
||||
private getWhereConditions(criteria: BusinessListingCriteria, user: JwtUser): SQL[] {
|
||||
const whereConditions: SQL[] = [];
|
||||
|
||||
if (criteria.city && criteria.searchType === 'exact') {
|
||||
|
|
@ -98,6 +98,9 @@ export class BusinessListingService {
|
|||
if (criteria.brokerName) {
|
||||
whereConditions.push(or(ilike(schema.users.firstname, `%${criteria.brokerName}%`), ilike(schema.users.lastname, `%${criteria.brokerName}%`)));
|
||||
}
|
||||
if (!user?.roles?.includes('ADMIN') ?? false) {
|
||||
whereConditions.push(or(eq(businesses.email, user?.username), ne(businesses.draft, true)));
|
||||
}
|
||||
whereConditions.push(and(eq(schema.users.customerType, 'professional'), eq(schema.users.customerSubType, 'broker')));
|
||||
return whereConditions;
|
||||
}
|
||||
|
|
@ -113,7 +116,7 @@ export class BusinessListingService {
|
|||
.from(businesses)
|
||||
.leftJoin(schema.users, eq(businesses.email, schema.users.email));
|
||||
|
||||
const whereConditions = this.getWhereConditions(criteria);
|
||||
const whereConditions = this.getWhereConditions(criteria, user);
|
||||
|
||||
if (whereConditions.length > 0) {
|
||||
const whereClause = and(...whereConditions);
|
||||
|
|
@ -124,7 +127,7 @@ export class BusinessListingService {
|
|||
query.limit(length).offset(start);
|
||||
|
||||
const data = await query;
|
||||
const totalCount = await this.getBusinessListingsCount(criteria);
|
||||
const totalCount = await this.getBusinessListingsCount(criteria, user);
|
||||
const results = data.map(r => r.business).map(r => convertDrizzleBusinessToBusiness(r));
|
||||
return {
|
||||
results,
|
||||
|
|
@ -132,10 +135,10 @@ export class BusinessListingService {
|
|||
};
|
||||
}
|
||||
|
||||
async getBusinessListingsCount(criteria: BusinessListingCriteria): Promise<number> {
|
||||
async getBusinessListingsCount(criteria: BusinessListingCriteria, user: JwtUser): Promise<number> {
|
||||
const countQuery = this.conn.select({ value: count() }).from(businesses).leftJoin(schema.users, eq(businesses.email, schema.users.email));
|
||||
|
||||
const whereConditions = this.getWhereConditions(criteria);
|
||||
const whereConditions = this.getWhereConditions(criteria, user);
|
||||
|
||||
if (whereConditions.length > 0) {
|
||||
const whereClause = and(...whereConditions);
|
||||
|
|
@ -147,12 +150,20 @@ export class BusinessListingService {
|
|||
}
|
||||
|
||||
async findBusinessesById(id: string, user: JwtUser): Promise<BusinessListing> {
|
||||
const conditions = [];
|
||||
if (!user?.roles?.includes('ADMIN') ?? false) {
|
||||
conditions.push(or(eq(businesses.email, user?.username), ne(businesses.draft, true)));
|
||||
}
|
||||
conditions.push(sql`${businesses.id} = ${id}`);
|
||||
let result = await this.conn
|
||||
.select()
|
||||
.from(businesses)
|
||||
.where(and(sql`${businesses.id} = ${id}`));
|
||||
result = result.filter(r => !r.draft || r.imageName === emailToDirName(user?.username) || user?.roles.includes('ADMIN'));
|
||||
.where(and(...conditions));
|
||||
if (result.length > 0) {
|
||||
return convertDrizzleBusinessToBusiness(result[0]) as BusinessListing;
|
||||
} else {
|
||||
throw new BadRequestException(`No entry available for ${id}`);
|
||||
}
|
||||
}
|
||||
|
||||
async findBusinessesByEmail(email: string, user: JwtUser): Promise<BusinessListing[]> {
|
||||
|
|
|
|||
|
|
@ -30,15 +30,11 @@ export class BusinessListingsController {
|
|||
find(@Request() req, @Body() criteria: BusinessListingCriteria): any {
|
||||
return this.listingsService.searchBusinessListings(criteria, req.user as JwtUser);
|
||||
}
|
||||
@UseGuards(OptionalJwtAuthGuard)
|
||||
@Post('findTotal')
|
||||
findTotal(@Body() criteria: BusinessListingCriteria): Promise<number> {
|
||||
return this.listingsService.getBusinessListingsCount(criteria);
|
||||
findTotal(@Request() req, @Body() criteria: BusinessListingCriteria): Promise<number> {
|
||||
return this.listingsService.getBusinessListingsCount(criteria, req.user as JwtUser);
|
||||
}
|
||||
// @UseGuards(OptionalJwtAuthGuard)
|
||||
// @Post('search')
|
||||
// search(@Request() req, @Body() criteria: BusinessListingCriteria): any {
|
||||
// return this.listingsService.searchBusinessListings(criteria.prompt);
|
||||
// }
|
||||
|
||||
@Post()
|
||||
create(@Body() listing: any) {
|
||||
|
|
|
|||
|
|
@ -31,9 +31,10 @@ export class CommercialPropertyListingsController {
|
|||
async find(@Request() req, @Body() criteria: CommercialPropertyListingCriteria): Promise<any> {
|
||||
return await this.listingsService.searchCommercialProperties(criteria, req.user as JwtUser);
|
||||
}
|
||||
@UseGuards(OptionalJwtAuthGuard)
|
||||
@Post('findTotal')
|
||||
findTotal(@Body() criteria: CommercialPropertyListingCriteria): Promise<number> {
|
||||
return this.listingsService.getCommercialPropertiesCount(criteria);
|
||||
findTotal(@Request() req, @Body() criteria: CommercialPropertyListingCriteria): Promise<number> {
|
||||
return this.listingsService.getCommercialPropertiesCount(criteria, req.user as JwtUser);
|
||||
}
|
||||
@Get('states/all')
|
||||
getStates(): any {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export class CommercialPropertyService {
|
|||
private fileService?: FileService,
|
||||
private geoService?: GeoService,
|
||||
) {}
|
||||
private getWhereConditions(criteria: CommercialPropertyListingCriteria): SQL[] {
|
||||
private getWhereConditions(criteria: CommercialPropertyListingCriteria, user: JwtUser): SQL[] {
|
||||
const whereConditions: SQL[] = [];
|
||||
|
||||
if (criteria.city && criteria.searchType === 'exact') {
|
||||
|
|
@ -49,6 +49,9 @@ export class CommercialPropertyService {
|
|||
if (criteria.title) {
|
||||
whereConditions.push(or(ilike(schema.commercials.title, `%${criteria.title}%`), ilike(schema.commercials.description, `%${criteria.title}%`)));
|
||||
}
|
||||
if (!user?.roles?.includes('ADMIN') ?? false) {
|
||||
whereConditions.push(or(eq(commercials.email, user?.username), ne(commercials.draft, true)));
|
||||
}
|
||||
whereConditions.push(and(eq(schema.users.customerType, 'professional')));
|
||||
return whereConditions;
|
||||
}
|
||||
|
|
@ -57,7 +60,7 @@ export class CommercialPropertyService {
|
|||
const start = criteria.start ? criteria.start : 0;
|
||||
const length = criteria.length ? criteria.length : 12;
|
||||
const query = this.conn.select({ commercial: commercials }).from(commercials).leftJoin(schema.users, eq(commercials.email, schema.users.email));
|
||||
const whereConditions = this.getWhereConditions(criteria);
|
||||
const whereConditions = this.getWhereConditions(criteria, user);
|
||||
|
||||
if (whereConditions.length > 0) {
|
||||
const whereClause = and(...whereConditions);
|
||||
|
|
@ -69,16 +72,16 @@ export class CommercialPropertyService {
|
|||
|
||||
const data = await query;
|
||||
const results = data.map(r => r.commercial).map(r => convertDrizzleCommercialToCommercial(r));
|
||||
const totalCount = await this.getCommercialPropertiesCount(criteria);
|
||||
const totalCount = await this.getCommercialPropertiesCount(criteria, user);
|
||||
|
||||
return {
|
||||
results,
|
||||
totalCount,
|
||||
};
|
||||
}
|
||||
async getCommercialPropertiesCount(criteria: CommercialPropertyListingCriteria): Promise<number> {
|
||||
async getCommercialPropertiesCount(criteria: CommercialPropertyListingCriteria, user: JwtUser): Promise<number> {
|
||||
const countQuery = this.conn.select({ value: count() }).from(schema.commercials).leftJoin(schema.users, eq(commercials.email, schema.users.email));
|
||||
const whereConditions = this.getWhereConditions(criteria);
|
||||
const whereConditions = this.getWhereConditions(criteria, user);
|
||||
|
||||
if (whereConditions.length > 0) {
|
||||
const whereClause = and(...whereConditions);
|
||||
|
|
@ -91,12 +94,20 @@ export class CommercialPropertyService {
|
|||
|
||||
// #### Find by ID ########################################
|
||||
async findCommercialPropertiesById(id: string, user: JwtUser): Promise<CommercialPropertyListing> {
|
||||
const conditions = [];
|
||||
if (!user?.roles?.includes('ADMIN') ?? false) {
|
||||
conditions.push(or(eq(commercials.email, user?.username), ne(commercials.draft, true)));
|
||||
}
|
||||
conditions.push(sql`${commercials.id} = ${id}`);
|
||||
let result = await this.conn
|
||||
.select()
|
||||
.from(commercials)
|
||||
.where(and(sql`${commercials.id} = ${id}`));
|
||||
result = result.filter(r => !r.draft || r.imagePath === emailToDirName(user?.username) || user?.roles.includes('ADMIN'));
|
||||
.where(and(...conditions));
|
||||
if (result.length > 0) {
|
||||
return convertDrizzleCommercialToCommercial(result[0]) as CommercialPropertyListing;
|
||||
} else {
|
||||
throw new BadRequestException(`No entry available for ${id}`);
|
||||
}
|
||||
}
|
||||
|
||||
// #### Find by User EMail ########################################
|
||||
|
|
|
|||
|
|
@ -83,9 +83,13 @@ export class DetailsBusinessListingComponent {
|
|||
this.user = await this.userService.getByMail(this.keycloakUser.email);
|
||||
this.mailinfo = createMailInfo(this.user);
|
||||
}
|
||||
try {
|
||||
this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, 'business'));
|
||||
this.listingUser = await this.userService.getByMail(this.listing.email);
|
||||
this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
ngOnDestroy() {
|
||||
this.validationMessagesService.clearMessages(); // Löschen Sie alle bestehenden Validierungsnachrichten
|
||||
|
|
@ -120,7 +124,7 @@ export class DetailsBusinessListingComponent {
|
|||
} else if (this.listing.franchiseResale) {
|
||||
typeOfRealEstate = 'Franchise Re-Sale';
|
||||
}
|
||||
return [
|
||||
const result = [
|
||||
{ label: 'Category', value: this.selectOptions.getBusiness(this.listing.type) },
|
||||
{ label: 'Located in', value: `${this.listing.location.name}, ${this.selectOptions.getState(this.listing.location.state)}` },
|
||||
{ label: 'Asking Price', value: `$${this.listing.price?.toLocaleString()}` },
|
||||
|
|
@ -133,5 +137,9 @@ export class DetailsBusinessListingComponent {
|
|||
{ label: 'Reason for Sale', value: this.listing.reasonForSale },
|
||||
{ label: 'Broker licensing', value: this.listing.brokerLicencing },
|
||||
];
|
||||
if (this.listing.draft) {
|
||||
result.push({ label: 'Draft', value: this.listing.draft ? 'Yes' : 'No' });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@
|
|||
|
||||
<div class="container mx-auto p-4">
|
||||
<div class="bg-white shadow-md rounded-lg overflow-hidden">
|
||||
@if(listing){
|
||||
<div class="p-6 relative">
|
||||
<h1 class="text-3xl font-bold mb-4">{{ listing?.title }}</h1>
|
||||
<button
|
||||
|
|
@ -231,5 +232,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ export class DetailsCommercialPropertyListingComponent {
|
|||
this.user = await this.userService.getByMail(this.keycloakUser.email);
|
||||
this.mailinfo = createMailInfo(this.user);
|
||||
}
|
||||
try {
|
||||
this.listing = (await lastValueFrom(this.listingsService.getListingById(this.id, 'commercialProperty'))) as CommercialPropertyListing;
|
||||
this.listingUser = await this.userService.getByMail(this.listing.email);
|
||||
this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description);
|
||||
|
|
@ -100,6 +101,13 @@ export class DetailsCommercialPropertyListingComponent {
|
|||
{ label: 'City', value: this.listing.location.name },
|
||||
{ label: 'Asking Price:', value: `$${this.listing.price?.toLocaleString()}` },
|
||||
];
|
||||
if (this.listing.draft) {
|
||||
this.propertyDetails.push({ label: 'Draft', value: this.listing.draft ? 'Yes' : 'No' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
//this.initFlowbite();
|
||||
}
|
||||
ngOnDestroy() {
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@
|
|||
<h3 class="font-semibold mb-2">Areas (Counties) we serve</h3>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
@for (area of user.areasServed; track area) {
|
||||
<span class="bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-sm">{{ area.county }}-{{ area.state }}</span>
|
||||
<span class="bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-sm">{{ area.county }}{{ area.county ? '-' : '' }}{{ area.state }}</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -251,7 +251,6 @@
|
|||
}
|
||||
<!-- Commercial Property Listings -->
|
||||
@if(commercialPropListings?.length>0){
|
||||
<div class="p-4">
|
||||
<h2 class="text-xl font-semibold mb-4">My Commercial Property Listings For Sale</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
@for (listing of commercialPropListings; track listing) {
|
||||
|
|
@ -270,7 +269,6 @@
|
|||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
} @if( user?.email===keycloakUser?.email || isAdmin()){
|
||||
<button class="mt-4 bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600" [routerLink]="['/account', user.id]">Edit</button>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,12 @@
|
|||
<i [class]="selectOptions.getIconAndTextColorType(listing.type)" class="mr-2"></i>
|
||||
<span [class]="selectOptions.getTextColorType(listing.type)" class="font-semibold">{{ selectOptions.getBusiness(listing.type) }}</span>
|
||||
</div>
|
||||
<h2 class="text-lg font-semibold mb-2">{{ listing.title }}</h2>
|
||||
<h2 class="text-lg font-semibold mb-2">
|
||||
{{ listing.title }}
|
||||
@if(listing.draft){
|
||||
<span class="bg-red-100 text-red-800 text-sm font-medium me-2 ml-2 px-2.5 py-0.5 rounded dark:bg-red-900 dark:text-red-300">Draft</span>
|
||||
}
|
||||
</h2>
|
||||
<p class="text-sm text-gray-600 mb-1">Asking price: {{ listing.price | currency }}</p>
|
||||
<p class="text-sm text-gray-600 mb-1">Sales revenue: {{ listing.salesRevenue | currency }}</p>
|
||||
<p class="text-sm text-gray-600 mb-1">Net profit: {{ listing.cashFlow | currency }}</p>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,12 @@
|
|||
<span class="bg-gray-200 text-gray-700 text-xs font-semibold px-2 py-1 rounded">{{ selectOptions.getState(listing.location.state) }}</span>
|
||||
<span class="text-gray-600 text-sm"><i [class]="selectOptions.getIconTypeOfCommercials(listing.type)" class="mr-1"></i> {{ selectOptions.getCommercialProperty(listing.type) }}</span>
|
||||
</div>
|
||||
<h3 class="text-lg font-semibold mb-2">{{ listing.title }}</h3>
|
||||
<h3 class="text-lg font-semibold mb-2">
|
||||
{{ listing.title }}
|
||||
@if(listing.draft){
|
||||
<span class="bg-red-100 text-red-800 text-sm font-medium me-2 ml-2 px-2.5 py-0.5 rounded dark:bg-red-900 dark:text-red-300">Draft</span>
|
||||
}
|
||||
</h3>
|
||||
<p class="text-gray-600 mb-2">{{ listing.location.name }}</p>
|
||||
<p class="text-xl font-bold mb-4">{{ listing.price | currency }}</p>
|
||||
<button [routerLink]="['/details-commercial-property-listing', listing.id]" class="bg-green-500 text-white px-4 py-2 rounded-full w-full hover:bg-green-600 transition duration-300">
|
||||
|
|
|
|||
Loading…
Reference in New Issue