cleanup + Property images

This commit is contained in:
Andreas Knuth 2024-05-05 15:30:10 +02:00
parent 9121ca1a69
commit bb5a408cdc
34 changed files with 1668 additions and 256 deletions

1326
bizmatch-server/broker.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@
"drop": "drizzle-kit drop", "drop": "drizzle-kit drop",
"migrate": "tsx src/drizzle/migrate.ts", "migrate": "tsx src/drizzle/migrate.ts",
"import": "tsx src/drizzle/import.ts", "import": "tsx src/drizzle/import.ts",
"generateTypes":"tsx src/drizzle/generateTypes.ts src/drizzle/schema.ts src/models/db.model.ts" "generateTypes": "tsx src/drizzle/generateTypes.ts src/drizzle/schema.ts src/models/db.model.ts"
}, },
"dependencies": { "dependencies": {
"@nestjs-modules/mailer": "^1.10.3", "@nestjs-modules/mailer": "^1.10.3",
@ -34,6 +34,7 @@
"@nestjs/passport": "^10.0.3", "@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"@nestjs/serve-static": "^4.0.1", "@nestjs/serve-static": "^4.0.1",
"cors": "^2.8.5",
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"drizzle-orm": "^0.30.8", "drizzle-orm": "^0.30.8",
"handlebars": "^4.7.8", "handlebars": "^4.7.8",
@ -80,6 +81,7 @@
"eslint-plugin-prettier": "^5.0.0", "eslint-plugin-prettier": "^5.0.0",
"jest": "^29.5.0", "jest": "^29.5.0",
"kysely-codegen": "^0.15.0", "kysely-codegen": "^0.15.0",
"pg-to-ts": "^4.1.1",
"prettier": "^3.0.0", "prettier": "^3.0.0",
"source-map-support": "^0.5.21", "source-map-support": "^0.5.21",
"supertest": "^6.3.3", "supertest": "^6.3.3",

View File

@ -31,7 +31,7 @@ const __dirname = path.dirname(__filename);
@Module({ @Module({
imports: [ConfigModule.forRoot({isGlobal: true}), MailModule, AuthModule, imports: [ConfigModule.forRoot({isGlobal: true}), MailModule, AuthModule,
ServeStaticModule.forRoot({ ServeStaticModule.forRoot({
rootPath: join(__dirname, '..', 'pictures'), // `public` ist das Verzeichnis, wo Ihre statischen Dateien liegen rootPath: join(__dirname, '../..', 'pictures'), // `public` ist das Verzeichnis, wo Ihre statischen Dateien liegen
}), }),
WinstonModule.forRoot({ WinstonModule.forRoot({
transports: [ transports: [

View File

@ -25,8 +25,8 @@ const generatedUserData = []
console.log(userData.length) console.log(userData.length)
for (const user of userData) { for (const user of userData) {
delete user.id delete user.id
user.licensedIn=user.licensedIn.map(l=>`${l['name']}|${l['value']}`)
const u = await db.insert(schema.users).values(user).returning({ insertedId: schema.users.id }); const u = await db.insert(schema.users).values(user).returning({ insertedId: schema.users.id });
// console.log(`--> ${u[0].insertedId}`)
generatedUserData.push(u[0].insertedId); generatedUserData.push(u[0].insertedId);
} }
//Business Listings //Business Listings
@ -45,7 +45,10 @@ filePath = `./data/commercials.json`
data = readFileSync(filePath, 'utf8'); data = readFileSync(filePath, 'utf8');
const commercialJsonData = JSON.parse(data) as CommercialPropertyListing[]; // Erwartet ein Array von Objekten const commercialJsonData = JSON.parse(data) as CommercialPropertyListing[]; // Erwartet ein Array von Objekten
for (const commercial of commercialJsonData) { for (const commercial of commercialJsonData) {
const id = commercial.id;
delete commercial.id delete commercial.id
commercial.imageOrder=['1.jpg'];
commercial.imagePath=id
commercial.created = getRandomDateWithinLastYear(); commercial.created = getRandomDateWithinLastYear();
commercial.userId = getRandomItem(generatedUserData); commercial.userId = getRandomItem(generatedUserData);
await db.insert(schema.commercials).values(commercial); await db.insert(schema.commercials).values(commercial);

View File

@ -46,7 +46,7 @@ CREATE TABLE IF NOT EXISTS "commercials" (
"website" varchar(255), "website" varchar(255),
"phoneNumber" varchar(255), "phoneNumber" varchar(255),
"imageOrder" varchar(30)[], "imageOrder" varchar(30)[],
"imagePath" varchar(30)[], "imagePath" varchar(50),
"created" timestamp, "created" timestamp,
"updated" timestamp, "updated" timestamp,
"visits" integer, "visits" integer,

View File

@ -1,5 +1,5 @@
{ {
"id": "e8d0776a-ea8b-4c75-8a3a-e741620c4c4d", "id": "f6d421f9-2394-4a1c-9268-9e46285f0a41",
"prevId": "00000000-0000-0000-0000-000000000000", "prevId": "00000000-0000-0000-0000-000000000000",
"version": "5", "version": "5",
"dialect": "pg", "dialect": "pg",
@ -300,7 +300,7 @@
}, },
"imagePath": { "imagePath": {
"name": "imagePath", "name": "imagePath",
"type": "varchar(30)[]", "type": "varchar(50)",
"primaryKey": false, "primaryKey": false,
"notNull": false "notNull": false
}, },

View File

@ -5,8 +5,8 @@
{ {
"idx": 0, "idx": 0,
"version": "5", "version": "5",
"when": 1713791559934, "when": 1714913766996,
"tag": "0000_safe_natasha_romanoff", "tag": "0000_third_spacker_dave",
"breakpoints": true "breakpoints": true
} }
] ]

View File

@ -69,7 +69,7 @@ export const commercials = pgTable('commercials', {
website: varchar('website', { length: 255 }), website: varchar('website', { length: 255 }),
phoneNumber: varchar('phoneNumber', { length: 255 }), phoneNumber: varchar('phoneNumber', { length: 255 }),
imageOrder:varchar('imageOrder',{length:30}).array(), imageOrder:varchar('imageOrder',{length:30}).array(),
imagePath:varchar('imagePath',{length:30}).array(), imagePath:varchar('imagePath',{length:50}),
created: timestamp('created'), created: timestamp('created'),
updated: timestamp('updated'), updated: timestamp('updated'),
visits: integer('visits'), visits: integer('visits'),

View File

@ -56,14 +56,13 @@ export class FileService {
return fs.existsSync(`./pictures/logo/${userId}.avif`)?true:false return fs.existsSync(`./pictures/logo/${userId}.avif`)?true:false
} }
async getPropertyImages(listingId: string): Promise<ImageProperty[]> { async getPropertyImages(listingId: string): Promise<string[]> {
const result: ImageProperty[] = [] const result: string[] = []
const directory = `./pictures/property/${listingId}` const directory = `./pictures/property/${listingId}`
if (fs.existsSync(directory)) { if (fs.existsSync(directory)) {
const files = await fs.readdir(directory); const files = await fs.readdir(directory);
files.forEach(f => { files.forEach(f => {
const image: ImageProperty = { name: f, id: '', code: '' }; result.push(f)
result.push(image)
}) })
return result; return result;
} else { } else {

View File

@ -7,6 +7,8 @@ import { SelectOptionsService } from '../select-options/select-options.service.j
import { ListingsService } from '../listings/listings.service.js'; import { ListingsService } from '../listings/listings.service.js';
import { Entity, EntityData } from 'redis-om'; import { Entity, EntityData } from 'redis-om';
import { businesses, commercials } from 'src/drizzle/schema.js';
import { CommercialPropertyListing } from 'src/models/db.model.js';
@Controller('image') @Controller('image')
export class ImageController { export class ImageController {
@ -38,16 +40,16 @@ export class ImageController {
@Get(':id') @Get(':id')
async getPropertyImagesById(@Param('id') id:string): Promise<any> { async getPropertyImagesById(@Param('id') id:string): Promise<any> {
// const result = await this.listingService.getCommercialPropertyListingById(id); const result = await this.listingService.findById(id,commercials);
// const listing = result as CommercialPropertyListing; const listing = result as CommercialPropertyListing;
// if (listing.imageOrder){ if (listing.imageOrder){
// return listing.imageOrder return listing.imageOrder
// } else { } else {
// const imageOrder = await this.fileService.getPropertyImages(id); const imageOrder = await this.fileService.getPropertyImages(id);
// listing.imageOrder=imageOrder; listing.imageOrder=imageOrder;
// this.listingService.saveListing(listing); this.listingService.updateListing(listing.id,listing,commercials);
// return imageOrder; return imageOrder;
// } }
} }
@Get('profileImages/:userids') @Get('profileImages/:userids')
async getProfileImagesForUsers(@Param('userids') userids:string): Promise<any> { async getProfileImagesForUsers(@Param('userids') userids:string): Promise<any> {

View File

@ -42,6 +42,9 @@ export class BusinessListingsController {
deleteById(@Param('id') id:string){ deleteById(@Param('id') id:string){
this.listingsService.deleteListing(id,businesses) this.listingsService.deleteListing(id,businesses)
} }
@Get('states/all')
getStates(): any {
return this.listingsService.getStates(businesses);
}
} }

View File

@ -88,7 +88,9 @@ export class ListingsService {
async deleteListing(id: string, table: typeof businesses | typeof commercials): Promise<void> { async deleteListing(id: string, table: typeof businesses | typeof commercials): Promise<void> {
await this.conn.delete(table).where(eq(table.id, id)); await this.conn.delete(table).where(eq(table.id, id));
} }
async getStates(table: typeof businesses | typeof commercials): Promise<any[]> {
return await this.conn.select({state: table.state,count: sql<number>`count(${table.id})`.mapWith(Number)}).from(table).groupBy(sql`${table.state}`).orderBy(sql`count desc`);
}
// ############################################################## // ##############################################################
// Images for commercial Properties // Images for commercial Properties
// ############################################################## // ##############################################################

View File

@ -1,6 +1,10 @@
import { NestFactory } from '@nestjs/core'; import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module.js'; import { AppModule } from './app.module.js';
import * as express from 'express';
import path, { join } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule); const app = await NestFactory.create(AppModule);
app.setGlobalPrefix('bizmatch'); app.setGlobalPrefix('bizmatch');

View File

@ -64,10 +64,9 @@ export interface CommercialPropertyListing {
website?: string; website?: string;
phoneNumber?: string; phoneNumber?: string;
imageOrder?: string[]; imageOrder?: string[];
imagePath?: string[]; imagePath?: string;
created?: Date; created?: Date;
updated?: Date; updated?: Date;
visits?: number; visits?: number;
lastVisit?: Date; lastVisit?: Date;
} }

View File

@ -1,155 +1,163 @@
import { BusinessListing, CommercialPropertyListing } from "./db.model"; import { BusinessListing, CommercialPropertyListing, User } from './db.model';
export interface StatesResult {
state: string;
count: number;
}
export interface KeyValue { export interface KeyValue {
name: string; name: string;
value: string; value: string;
} }
export interface KeyValueRatio { export interface KeyValueRatio {
label: string; label: string;
value: number; value: number;
} }
export interface KeyValueStyle { export interface KeyValueStyle {
name: string; name: string;
value: string; value: string;
icon:string; icon: string;
bgColorClass:string; bgColorClass: string;
textColorClass:string; textColorClass: string;
} }
export type SelectOption<T = number> = { export type SelectOption<T = number> = {
value: T; value: T;
label: string; label: string;
}; };
export type ImageType = { export type ImageType = {
name:'propertyPicture'|'companyLogo'|'profile',upload:string,delete:string, name: 'propertyPicture' | 'companyLogo' | 'profile';
} upload: string;
delete: string;
};
export type ListingCategory = { export type ListingCategory = {
name: 'business' | 'commercialProperty' name: 'business' | 'commercialProperty';
} };
export type ListingType = export type ListingType = BusinessListing | CommercialPropertyListing;
| BusinessListing
| CommercialPropertyListing;
export type ResponseBusinessListingArray = { export type ResponseBusinessListingArray = {
data:BusinessListing[], data: BusinessListing[];
total:number total: number;
} };
export type ResponseBusinessListing = { export type ResponseBusinessListing = {
data:BusinessListing data: BusinessListing;
} };
export type ResponseCommercialPropertyListingArray = { export type ResponseCommercialPropertyListingArray = {
data:CommercialPropertyListing[], data: CommercialPropertyListing[];
total:number total: number;
} };
export type ResponseCommercialPropertyListing = { export type ResponseCommercialPropertyListing = {
data:CommercialPropertyListing data: CommercialPropertyListing;
} };
export type ResponseUsersArray = {
data: User[];
total: number;
};
export interface ListingCriteria { export interface ListingCriteria {
start:number, start: number;
length:number, length: number;
page:number, page: number;
pageCount:number, pageCount: number;
type:number, type: number;
state:string, state: string;
minPrice:number, minPrice: number;
maxPrice:number, maxPrice: number;
realEstateChecked:boolean, realEstateChecked: boolean;
title:string, title: string;
category:'professional|broker' category: 'professional|broker';
} }
export interface KeycloakUser { export interface KeycloakUser {
id: string id: string;
createdTimestamp: number createdTimestamp: number;
username: string username: string;
enabled: boolean enabled: boolean;
totp: boolean totp: boolean;
emailVerified: boolean emailVerified: boolean;
firstName: string firstName: string;
lastName: string lastName: string;
email: string email: string;
disableableCredentialTypes: any[] disableableCredentialTypes: any[];
requiredActions: any[] requiredActions: any[];
notBefore: number notBefore: number;
access: Access access: Access;
} }
export interface Access { export interface Access {
manageGroupMembership: boolean manageGroupMembership: boolean;
view: boolean view: boolean;
mapRoles: boolean mapRoles: boolean;
impersonate: boolean impersonate: boolean;
manage: boolean manage: boolean;
} }
export interface Subscription { export interface Subscription {
id: string; id: string;
userId:string userId: string;
level: string; level: string;
start: Date; start: Date;
modified: Date; modified: Date;
end: Date; end: Date;
status: string; status: string;
invoices: Array<Invoice>; invoices: Array<Invoice>;
} }
export interface Invoice { export interface Invoice {
id: string, id: string;
date: Date, date: Date;
price: number price: number;
} }
export interface JwtToken { export interface JwtToken {
exp: number; exp: number;
iat: number; iat: number;
auth_time: number; auth_time: number;
jti: string; jti: string;
iss: string; iss: string;
aud: string; aud: string;
sub: string; sub: string;
typ: string; typ: string;
azp: string; azp: string;
nonce: string; nonce: string;
session_state: string; session_state: string;
acr: string; acr: string;
realm_access: Realmaccess; realm_access: Realmaccess;
resource_access: Resourceaccess; resource_access: Resourceaccess;
scope: string; scope: string;
sid: string; sid: string;
email_verified: boolean; email_verified: boolean;
name: string; name: string;
preferred_username: string; preferred_username: string;
given_name: string; given_name: string;
family_name: string; family_name: string;
email: string; email: string;
user_id: string; user_id: string;
} }
interface Resourceaccess { interface Resourceaccess {
account: Realmaccess; account: Realmaccess;
} }
interface Realmaccess { interface Realmaccess {
roles: string[]; roles: string[];
} }
export interface PageEvent { export interface PageEvent {
first: number; first: number;
rows: number; rows: number;
page: number; page: number;
pageCount: number; pageCount: number;
} }
export interface AutoCompleteCompleteEvent { export interface AutoCompleteCompleteEvent {
originalEvent: Event; originalEvent: Event;
query: string; query: string;
} }
export interface MailInfo { export interface MailInfo {
sender: Sender; sender: Sender;
userId: string; userId: string;
} }
export interface Sender { export interface Sender {
name?: string; name?: string;
email?: string; email?: string;
phoneNumber?: string; phoneNumber?: string;
state?: string; state?: string;
comments?: string; comments?: string;
} }
export interface ImageProperty { export interface ImageProperty {
id:string; id: string;
code:string; code: string;
name:string; name: string;
} }

View File

@ -51,8 +51,11 @@ export class UserService {
const start = criteria.start ? criteria.start : 0; const start = criteria.start ? criteria.start : 0;
const length = criteria.length ? criteria.length : 12; const length = criteria.length ? criteria.length : 12;
const conditions = this.getConditions(criteria) const conditions = this.getConditions(criteria)
const users = await this.conn.select().from(schema.users).where(and(...conditions)).offset(start).limit(length) const [data, total] = await Promise.all([
return users this.conn.select().from(schema.users).where(and(...conditions)).offset(start).limit(length),
this.conn.select({ count: sql`count(*)` }).from(schema.users).where(and(...conditions)).then((result) => Number(result[0].count)),
]);
return { total, data };
} }
} }

95
bizmatch/dbschema.ts Normal file
View File

@ -0,0 +1,95 @@
/* tslint:disable */
/* eslint-disable */
/**
* AUTO-GENERATED FILE - DO NOT EDIT!
*
* This file was automatically generated by pg-to-ts v.4.1.1
* $ pg-to-ts generate -c postgresql://username:password@localhost:5432/bizmatch -t businesses -s public
*
*/
export type Json = unknown;
// Table businesses
export interface Businesses {
id: string;
userId: string | null;
type: number | null;
title: string | null;
description: string | null;
city: string | null;
state: string | null;
price: number | null;
favoritesForUser: string[] | null;
draft: boolean | null;
listingsCategory: string | null;
realEstateIncluded: boolean | null;
leasedLocation: boolean | null;
franchiseResale: boolean | null;
salesRevenue: number | null;
cashFlow: number | null;
supportAndTraining: string | null;
employees: number | null;
established: number | null;
internalListingNumber: number | null;
reasonForSale: string | null;
brokerLicencing: string | null;
internals: string | null;
created: Date | null;
updated: Date | null;
visits: number | null;
lastVisit: Date | null;
}
export interface BusinessesInput {
id?: string;
userId?: string | null;
type?: number | null;
title?: string | null;
description?: string | null;
city?: string | null;
state?: string | null;
price?: number | null;
favoritesForUser?: string[] | null;
draft?: boolean | null;
listingsCategory?: string | null;
realEstateIncluded?: boolean | null;
leasedLocation?: boolean | null;
franchiseResale?: boolean | null;
salesRevenue?: number | null;
cashFlow?: number | null;
supportAndTraining?: string | null;
employees?: number | null;
established?: number | null;
internalListingNumber?: number | null;
reasonForSale?: string | null;
brokerLicencing?: string | null;
internals?: string | null;
created?: Date | null;
updated?: Date | null;
visits?: number | null;
lastVisit?: Date | null;
}
const businesses = {
tableName: 'businesses',
columns: ['id', 'userId', 'type', 'title', 'description', 'city', 'state', 'price', 'favoritesForUser', 'draft', 'listingsCategory', 'realEstateIncluded', 'leasedLocation', 'franchiseResale', 'salesRevenue', 'cashFlow', 'supportAndTraining', 'employees', 'established', 'internalListingNumber', 'reasonForSale', 'brokerLicencing', 'internals', 'created', 'updated', 'visits', 'lastVisit'],
requiredForInsert: [],
primaryKey: 'id',
foreignKeys: { userId: { table: 'users', column: 'id', $type: null as unknown /* users */ }, },
$type: null as unknown as Businesses,
$input: null as unknown as BusinessesInput
} as const;
export interface TableTypes {
businesses: {
select: Businesses;
input: BusinessesInput;
};
}
export const tables = {
businesses,
}

View File

@ -1,6 +1,11 @@
{ {
"/api": { "/api": {
"target": "http://localhost:3000", "target": "http://localhost:3000",
"secure": false "secure": false
} },
"/property": {
"target": "http://localhost:3000",
"secure": false,
"changeOrigin": true
}
} }

View File

@ -7,6 +7,7 @@
<p-button icon="pi pi-times" [rounded]="true" severity="danger" (click)="back()"></p-button> <p-button icon="pi pi-times" [rounded]="true" severity="danger" (click)="back()"></p-button>
</div> </div>
<!-- <div class="text-500 mb-5">Egestas sed tempus urna et pharetra pharetra massa massa ultricies.</div> --> <!-- <div class="text-500 mb-5">Egestas sed tempus urna et pharetra pharetra massa massa ultricies.</div> -->
@if(listing){
<div class="grid"> <div class="grid">
<div class="col-12 md:col-6"> <div class="col-12 md:col-6">
<ul class="list-none p-0 m-0 border-top-1 border-300"> <ul class="list-none p-0 m-0 border-top-1 border-300">
@ -95,6 +96,7 @@
</div> </div>
</div> </div>
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>

View File

@ -6,7 +6,7 @@ import { MessageService } from 'primeng/api';
import { GalleriaModule } from 'primeng/galleria'; import { GalleriaModule } from 'primeng/galleria';
import { lastValueFrom } from 'rxjs'; import { lastValueFrom } from 'rxjs';
import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model'; import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
import { ImageProperty, ListingCriteria, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model'; import { ListingCriteria, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model';
import { environment } from '../../../../environments/environment'; import { environment } from '../../../../environments/environment';
import { ListingsService } from '../../../services/listings.service'; import { ListingsService } from '../../../services/listings.service';
import { MailService } from '../../../services/mail.service'; import { MailService } from '../../../services/mail.service';
@ -43,11 +43,10 @@ export class DetailsBusinessListingComponent {
}, },
]; ];
private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined; private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined;
private type: 'business' | 'commercialProperty' | undefined = this.activatedRoute.snapshot.params['type'] as 'business' | 'commercialProperty' | undefined;
listing: BusinessListing; listing: BusinessListing;
criteria: ListingCriteria; criteria: ListingCriteria;
mailinfo: MailInfo; mailinfo: MailInfo;
propertyImages: ImageProperty[] = []; propertyImages: string[] = [];
environment = environment; environment = environment;
user: User; user: User;
description: SafeHtml; description: SafeHtml;
@ -69,7 +68,7 @@ export class DetailsBusinessListingComponent {
} }
async ngOnInit() { async ngOnInit() {
this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, this.type)); this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, 'business'));
this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id); this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id);
this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description); this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description);
} }

View File

@ -7,6 +7,7 @@
<p-button icon="pi pi-times" [rounded]="true" severity="danger" (click)="back()"></p-button> <p-button icon="pi pi-times" [rounded]="true" severity="danger" (click)="back()"></p-button>
</div> </div>
<!-- <div class="text-500 mb-5">Egestas sed tempus urna et pharetra pharetra massa massa ultricies.</div> --> <!-- <div class="text-500 mb-5">Egestas sed tempus urna et pharetra pharetra massa massa ultricies.</div> -->
@if(listing){
<div class="grid"> <div class="grid">
<div class="col-12 md:col-6"> <div class="col-12 md:col-6">
<ul class="list-none p-0 m-0 border-top-1 border-300"> <ul class="list-none p-0 m-0 border-top-1 border-300">
@ -41,7 +42,7 @@
</ul> </ul>
<p-galleria [value]="propertyImages" [showIndicators]="true" [showThumbnails]="false" [responsiveOptions]="responsiveOptions" [containerStyle]="{ 'max-width': '640px' }" [numVisible]="5"> <p-galleria [value]="propertyImages" [showIndicators]="true" [showThumbnails]="false" [responsiveOptions]="responsiveOptions" [containerStyle]="{ 'max-width': '640px' }" [numVisible]="5">
<ng-template pTemplate="item" let-item> <ng-template pTemplate="item" let-item>
<img src="{{ environment.apiBaseUrl }}/property/{{ listing.id }}/{{ item.name }}" style="width: 100%" /> <img src="property/{{ listing.imagePath }}/{{ item }}" style="width: 100%" />
</ng-template> </ng-template>
<!-- <ng-template pTemplate="thumbnail" let-item> <!-- <ng-template pTemplate="thumbnail" let-item>
<div class="grid grid-nogutter justify-content-center"> <div class="grid grid-nogutter justify-content-center">
@ -85,6 +86,7 @@
</div> </div>
</div> </div>
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>

View File

@ -6,7 +6,7 @@ import { MessageService } from 'primeng/api';
import { GalleriaModule } from 'primeng/galleria'; import { GalleriaModule } from 'primeng/galleria';
import { lastValueFrom } from 'rxjs'; import { lastValueFrom } from 'rxjs';
import { CommercialPropertyListing, User } from '../../../../../../bizmatch-server/src/models/db.model'; import { CommercialPropertyListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
import { ImageProperty, ListingCriteria, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model'; import { ListingCriteria, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model';
import { environment } from '../../../../environments/environment'; import { environment } from '../../../../environments/environment';
import { ListingsService } from '../../../services/listings.service'; import { ListingsService } from '../../../services/listings.service';
import { MailService } from '../../../services/mail.service'; import { MailService } from '../../../services/mail.service';
@ -43,11 +43,10 @@ export class DetailsCommercialPropertyListingComponent {
}, },
]; ];
private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined; private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined;
private type: 'business' | 'commercialProperty' | undefined = this.activatedRoute.snapshot.params['type'] as 'business' | 'commercialProperty' | undefined;
listing: CommercialPropertyListing; listing: CommercialPropertyListing;
criteria: ListingCriteria; criteria: ListingCriteria;
mailinfo: MailInfo; mailinfo: MailInfo;
propertyImages: ImageProperty[] = []; propertyImages: string[] = [];
environment = environment; environment = environment;
user: User; user: User;
description: SafeHtml; description: SafeHtml;
@ -69,7 +68,7 @@ export class DetailsCommercialPropertyListingComponent {
} }
async ngOnInit() { async ngOnInit() {
this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, this.type)); this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, 'commercialProperty'));
this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id); this.propertyImages = await this.listingsService.getPropertyImages(this.listing.id);
this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description); this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description);
} }

View File

@ -43,6 +43,7 @@
</div> </div>
</div> </div>
</div> </div>
<p-button icon="pi pi-times" [rounded]="true" severity="danger" (click)="back()"></p-button>
</div> </div>
<p class="mt-2 text-700 line-height-3 text-l font-semibold">{{ user.description }}</p> <p class="mt-2 text-700 line-height-3 text-l font-semibold">{{ user.description }}</p>
</div> </div>

View File

@ -3,9 +3,9 @@
} }
.container { .container {
//background-image: url(../../../assets/images/index-bg.webp); background-image: url(../../../assets/images/index-bg.webp);
// background-image: url(../../../assets/images/1_Version.jpg); // background-image: url(../../../assets/images/1_Version.jpg);
background-image: url(../../../assets/images/2_1_Version.jpg); //background-image: url(../../../assets/images/2_1_Version.jpg);
background-size: cover; background-size: cover;
background-position: center; background-position: center;
height: 100vh; height: 100vh;

View File

@ -2,7 +2,10 @@
<div class="search"> <div class="search">
<div class="wrapper"> <div class="wrapper">
<div class="grid p-4 align-items-center"> <div class="grid p-4 align-items-center">
<div class="col-1 col-offset-7"> <div class="col-2">
<p-dropdown [options]="states" [(ngModel)]="criteria.state" optionLabel="name" optionValue="value" [showClear]="true" placeholder="Location" [style]="{ width: '100%' }"></p-dropdown>
</div>
<div class="col-1 col-offset-9">
<p-button label="Refine" (click)="search()"></p-button> <p-button label="Refine" (click)="search()"></p-button>
</div> </div>
</div> </div>
@ -41,7 +44,7 @@
} }
</div> </div>
<div class="mb-2 surface-200 flex align-items-center justify-content-center"> <div class="mb-2 surface-200 flex align-items-center justify-content-center">
<div class="mx-1 text-color">Total number of Listings: {{ totalRecords }}</div> <div class="mx-1 text-color">Total number of Professionals/Brokers: {{ totalRecords }}</div>
<p-paginator (onPageChange)="onPageChange($event)" [first]="first" [rows]="rows" [totalRecords]="totalRecords" [rowsPerPageOptions]="[12, 24, 48]"></p-paginator> <p-paginator (onPageChange)="onPageChange($event)" [first]="first" [rows]="rows" [totalRecords]="totalRecords" [rowsPerPageOptions]="[12, 24, 48]"></p-paginator>
</div> </div>
</div> </div>

View File

@ -66,11 +66,17 @@ export class BrokerListingsComponent {
this.init(); this.init();
}); });
} }
async ngOnInit() {} async ngOnInit() {
const statesResult = await this.listingsService.getAllStates('business');
this.states = statesResult.map(s => s.state).map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
}
async init() { async init() {
this.listings = []; this.search();
this.filteredListings = []; }
this.users = await this.userService.search(this.criteria); async search() {
const usersReponse = await this.userService.search(this.criteria);
this.users = usersReponse.data;
this.totalRecords = usersReponse.total;
const profiles = await this.imageService.getProfileImagesForUsers(this.users.map(u => u.id)); const profiles = await this.imageService.getProfileImagesForUsers(this.users.map(u => u.id));
const logos = await this.imageService.getCompanyLogosForUsers(this.users.map(u => u.id)); const logos = await this.imageService.getCompanyLogosForUsers(this.users.map(u => u.id));
this.users.forEach(u => { this.users.forEach(u => {
@ -80,28 +86,12 @@ export class BrokerListingsComponent {
this.cdRef.markForCheck(); this.cdRef.markForCheck();
this.cdRef.detectChanges(); this.cdRef.detectChanges();
} }
setStates() {
this.statesSet = new Set();
this.listings.forEach(l => {
if (l.state) {
this.statesSet.add(l.state);
}
});
this.states = [...this.statesSet].map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
}
async search() {
this.listings = await this.listingsService.getListings(this.criteria, 'professionals_brokers');
this.setStates();
this.totalRecords = this.listings.length;
this.filteredListings = [...this.listings].splice(this.first, this.rows);
this.cdRef.markForCheck();
this.cdRef.detectChanges();
}
onPageChange(event: any) { onPageChange(event: any) {
this.criteria.start = event.first; this.criteria.start = event.first;
this.criteria.length = event.rows; this.criteria.length = event.rows;
this.criteria.page = event.page; this.criteria.page = event.page;
this.criteria.pageCount = event.pageCount; this.criteria.pageCount = event.pageCount;
this.search();
} }
imageErrorHandler(listing: ListingType) { imageErrorHandler(listing: ListingType) {
// listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann // listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann

View File

@ -10,13 +10,12 @@ import { InputTextModule } from 'primeng/inputtext';
import { PaginatorModule } from 'primeng/paginator'; import { PaginatorModule } from 'primeng/paginator';
import { StyleClassModule } from 'primeng/styleclass'; import { StyleClassModule } from 'primeng/styleclass';
import { ToggleButtonModule } from 'primeng/togglebutton'; import { ToggleButtonModule } from 'primeng/togglebutton';
import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model'; import { BusinessListing } from '../../../../../../bizmatch-server/src/models/db.model';
import { ListingCriteria, ListingType } from '../../../../../../bizmatch-server/src/models/main.model'; import { ListingCriteria, ListingType } from '../../../../../../bizmatch-server/src/models/main.model';
import { environment } from '../../../../environments/environment'; import { environment } from '../../../../environments/environment';
import { ImageService } from '../../../services/image.service'; import { ImageService } from '../../../services/image.service';
import { ListingsService } from '../../../services/listings.service'; import { ListingsService } from '../../../services/listings.service';
import { SelectOptionsService } from '../../../services/select-options.service'; import { SelectOptionsService } from '../../../services/select-options.service';
import { UserService } from '../../../services/user.service';
import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils'; import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils';
@Component({ @Component({
@ -29,7 +28,6 @@ import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler }
export class BusinessListingsComponent { export class BusinessListingsComponent {
environment = environment; environment = environment;
listings: Array<BusinessListing>; listings: Array<BusinessListing>;
users: Array<User>;
filteredListings: Array<BusinessListing>; filteredListings: Array<BusinessListing>;
criteria: ListingCriteria; criteria: ListingCriteria;
realEstateChecked: boolean; realEstateChecked: boolean;
@ -37,7 +35,6 @@ export class BusinessListingsComponent {
minPrice: string; minPrice: string;
type: string; type: string;
states = []; states = [];
statesSet = new Set();
state: string; state: string;
first: number = 0; first: number = 0;
rows: number = 12; rows: number = 12;
@ -48,7 +45,6 @@ export class BusinessListingsComponent {
constructor( constructor(
public selectOptions: SelectOptionsService, public selectOptions: SelectOptionsService,
private listingsService: ListingsService, private listingsService: ListingsService,
private userService: UserService,
private activatedRoute: ActivatedRoute, private activatedRoute: ActivatedRoute,
private router: Router, private router: Router,
private cdRef: ChangeDetectorRef, private cdRef: ChangeDetectorRef,
@ -68,30 +64,14 @@ export class BusinessListingsComponent {
} }
async ngOnInit() {} async ngOnInit() {}
async init() { async init() {
this.users = []; const statesResult = await this.listingsService.getAllStates('business');
this.listings = await this.listingsService.getListings(this.criteria, 'business'); this.states = statesResult.map(s => s.state).map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
this.search();
this.setStates();
//this.filteredListings=[...this.listings];
this.totalRecords = this.listings.length;
//this.filteredListings=[...this.listings].splice(this.first,this.rows);
this.cdRef.markForCheck();
this.cdRef.detectChanges();
}
setStates() {
this.statesSet = new Set();
this.listings.forEach(l => {
if (l.state) {
this.statesSet.add(l.state);
}
});
this.states = [...this.statesSet].map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
} }
async search() { async search() {
this.listings = await this.listingsService.getListings(this.criteria, 'business'); const listingReponse = await this.listingsService.getListings(this.criteria, 'business');
this.setStates(); this.listings = listingReponse.data;
this.totalRecords = this.listings.length; this.totalRecords = listingReponse.total;
this.filteredListings = [...this.listings].splice(this.first, this.rows);
this.cdRef.markForCheck(); this.cdRef.markForCheck();
this.cdRef.detectChanges(); this.cdRef.detectChanges();
} }
@ -100,6 +80,7 @@ export class BusinessListingsComponent {
this.criteria.length = event.rows; this.criteria.length = event.rows;
this.criteria.page = event.page; this.criteria.page = event.page;
this.criteria.pageCount = event.pageCount; this.criteria.pageCount = event.pageCount;
this.search();
} }
imageErrorHandler(listing: ListingType) { imageErrorHandler(listing: ListingType) {
// listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann // listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann

View File

@ -20,7 +20,7 @@
<article class="flex flex-column md:flex-row w-full gap-3 p-3 surface-card"> <article class="flex flex-column md:flex-row w-full gap-3 p-3 surface-card">
<div class="relative"> <div class="relative">
@if (listing.imageOrder.length>0){ @if (listing.imageOrder.length>0){
<img src="{{ environment.apiBaseUrl }}/property/{{ listing.id }}/{{ listing.imageOrder[0] }}" alt="Image" class="border-round w-full h-full md:w-12rem md:h-9rem" /> <img src="property/{{ listing.imagePath }}/{{ listing.imageOrder[0] }}" alt="Image" class="border-round w-full h-full md:w-12rem md:h-9rem" />
} @else { } @else {
<!-- <img src="{{environment.apiBaseUrl}}/property/{{listing.id}}/{{listing.imageOrder[0].name}}" alt="Image" class="border-round w-full h-full md:w-12rem md:h-9rem"> --> <!-- <img src="{{environment.apiBaseUrl}}/property/{{listing.id}}/{{listing.imageOrder[0].name}}" alt="Image" class="border-round w-full h-full md:w-12rem md:h-9rem"> -->
<img src="assets/images/placeholder_properties.jpg" alt="Image" class="border-round w-full h-full md:w-12rem md:h-9rem" /> <img src="assets/images/placeholder_properties.jpg" alt="Image" class="border-round w-full h-full md:w-12rem md:h-9rem" />

View File

@ -10,13 +10,12 @@ import { InputTextModule } from 'primeng/inputtext';
import { PaginatorModule } from 'primeng/paginator'; import { PaginatorModule } from 'primeng/paginator';
import { StyleClassModule } from 'primeng/styleclass'; import { StyleClassModule } from 'primeng/styleclass';
import { ToggleButtonModule } from 'primeng/togglebutton'; import { ToggleButtonModule } from 'primeng/togglebutton';
import { CommercialPropertyListing, User } from '../../../../../../bizmatch-server/src/models/db.model'; import { CommercialPropertyListing } from '../../../../../../bizmatch-server/src/models/db.model';
import { ListingCriteria, ListingType } from '../../../../../../bizmatch-server/src/models/main.model'; import { ListingCriteria, ListingType } from '../../../../../../bizmatch-server/src/models/main.model';
import { environment } from '../../../../environments/environment'; import { environment } from '../../../../environments/environment';
import { ImageService } from '../../../services/image.service'; import { ImageService } from '../../../services/image.service';
import { ListingsService } from '../../../services/listings.service'; import { ListingsService } from '../../../services/listings.service';
import { SelectOptionsService } from '../../../services/select-options.service'; import { SelectOptionsService } from '../../../services/select-options.service';
import { UserService } from '../../../services/user.service';
import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils'; import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils';
@Component({ @Component({
@ -29,7 +28,6 @@ import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler }
export class CommercialPropertyListingsComponent { export class CommercialPropertyListingsComponent {
environment = environment; environment = environment;
listings: Array<CommercialPropertyListing>; listings: Array<CommercialPropertyListing>;
users: Array<User>;
filteredListings: Array<CommercialPropertyListing>; filteredListings: Array<CommercialPropertyListing>;
criteria: ListingCriteria; criteria: ListingCriteria;
realEstateChecked: boolean; realEstateChecked: boolean;
@ -48,7 +46,6 @@ export class CommercialPropertyListingsComponent {
constructor( constructor(
public selectOptions: SelectOptionsService, public selectOptions: SelectOptionsService,
private listingsService: ListingsService, private listingsService: ListingsService,
private userService: UserService,
private activatedRoute: ActivatedRoute, private activatedRoute: ActivatedRoute,
private router: Router, private router: Router,
private cdRef: ChangeDetectorRef, private cdRef: ChangeDetectorRef,
@ -67,41 +64,24 @@ export class CommercialPropertyListingsComponent {
} }
async ngOnInit() {} async ngOnInit() {}
async init() { async init() {
this.users = []; const statesResult = await this.listingsService.getAllStates('business');
this.listings = await this.listingsService.getListings(this.criteria, 'commercialProperty'); this.states = statesResult.map(s => s.state).map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
this.search();
}
this.setStates();
//this.filteredListings=[...this.listings];
this.totalRecords = this.listings.length;
//this.filteredListings=[...this.listings].splice(this.first,this.rows);
this.cdRef.markForCheck();
this.cdRef.detectChanges();
}
setStates() {
this.statesSet = new Set();
this.listings.forEach(l => {
if (l.state) {
this.statesSet.add(l.state);
}
});
this.states = [...this.statesSet].map(ls => ({ name: this.selectOptions.getState(ls as string), value: ls }));
}
async search() { async search() {
this.listings = await this.listingsService.getListings(this.criteria, 'commercialProperty'); const listingReponse = await this.listingsService.getListings(this.criteria, 'commercialProperty');
this.setStates(); this.listings = listingReponse.data;
this.totalRecords = this.listings.length; this.totalRecords = listingReponse.total;
this.filteredListings = [...this.listings].splice(this.first, this.rows);
this.cdRef.markForCheck(); this.cdRef.markForCheck();
this.cdRef.detectChanges(); this.cdRef.detectChanges();
} }
onPageChange(event: any) { onPageChange(event: any) {
//this.first = event.first;
//this.rows = event.rows;
//this.filteredListings=[...this.listings].splice(this.first,this.rows);
this.criteria.start = event.first; this.criteria.start = event.first;
this.criteria.length = event.rows; this.criteria.length = event.rows;
this.criteria.page = event.page; this.criteria.page = event.page;
this.criteria.pageCount = event.pageCount; this.criteria.pageCount = event.pageCount;
this.search();
} }
imageErrorHandler(listing: ListingType) { imageErrorHandler(listing: ListingType) {
// listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann // listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann

View File

@ -61,7 +61,7 @@ export class EditBusinessListingComponent {
maxFileSize = 3000000; maxFileSize = 3000000;
uploadUrl: string; uploadUrl: string;
environment = environment; environment = environment;
propertyImages: ImageProperty[]; propertyImages: string[];
responsiveOptions = [ responsiveOptions = [
{ {
breakpoint: '1199px', breakpoint: '1199px',

View File

@ -103,8 +103,8 @@
@for (image of propertyImages; track image) { @for (image of propertyImages; track image) {
<span cdkDropList mixedCdkDropList> <span cdkDropList mixedCdkDropList>
<div cdkDrag mixedCdkDragSizeHelper class="image-wrap"> <div cdkDrag mixedCdkDragSizeHelper class="image-wrap">
<img src="{{ environment.apiBaseUrl }}/property/{{ listing.id }}/{{ image.name }}" [alt]="image.name" class="shadow-2" cdkDrag /> <img src="property/{{ listing.id }}/{{ image }}" [alt]="image" class="shadow-2" cdkDrag />
<fa-icon [icon]="faTrash" (click)="deleteConfirm(image.name)"></fa-icon> <fa-icon [icon]="faTrash" (click)="deleteConfirm(image)"></fa-icon>
</div> </div>
</span> </span>
} }

View File

@ -63,7 +63,7 @@ export class EditCommercialPropertyListingComponent {
maxFileSize = 3000000; maxFileSize = 3000000;
uploadUrl: string; uploadUrl: string;
environment = environment; environment = environment;
propertyImages: ImageProperty[]; propertyImages: string[];
responsiveOptions = [ responsiveOptions = [
{ {
breakpoint: '1199px', breakpoint: '1199px',

View File

@ -2,7 +2,7 @@ import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, lastValueFrom } from 'rxjs'; import { Observable, lastValueFrom } from 'rxjs';
import { BusinessListing } from '../../../../bizmatch-server/src/models/db.model'; import { BusinessListing } from '../../../../bizmatch-server/src/models/db.model';
import { ImageProperty, ListingCriteria, ListingType, ResponseBusinessListingArray } from '../../../../bizmatch-server/src/models/main.model'; import { ListingCriteria, ListingType, ResponseBusinessListingArray, ResponseCommercialPropertyListingArray, StatesResult } from '../../../../bizmatch-server/src/models/main.model';
import { environment } from '../../environments/environment'; import { environment } from '../../environments/environment';
@Injectable({ @Injectable({
@ -15,9 +15,9 @@ export class ListingsService {
// getAllListings():Observable<ListingType[]>{ // getAllListings():Observable<ListingType[]>{
// return this.http.get<ListingType[]>(`${this.apiBaseUrl}/bizmatch/business-listings`); // return this.http.get<ListingType[]>(`${this.apiBaseUrl}/bizmatch/business-listings`);
// } // }
async getListings(criteria: ListingCriteria, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty'): Promise<ListingType[]> { async getListings(criteria: ListingCriteria, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty'): Promise<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray> {
const result = await lastValueFrom(this.http.post<ResponseBusinessListingArray>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/search`, criteria)); const result = await lastValueFrom(this.http.post<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/search`, criteria));
return result.data; return result;
} }
getListingById(id: string, listingsCategory?: 'business' | 'commercialProperty'): Observable<ListingType> { getListingById(id: string, listingsCategory?: 'business' | 'commercialProperty'): Observable<ListingType> {
const result = this.http.get<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`); const result = this.http.get<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`);
@ -33,13 +33,17 @@ export class ListingsService {
return await lastValueFrom(this.http.post<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}`, listing)); return await lastValueFrom(this.http.post<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}`, listing));
} }
} }
async getAllStates(listingsCategory?: 'business' | 'commercialProperty'): Promise<StatesResult[]> {
const result = lastValueFrom(this.http.get<StatesResult[]>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/states/all`));
return result;
}
async deleteListing(id: string, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty') { async deleteListing(id: string, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty') {
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`)); await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`));
} }
async getPropertyImages(id: string): Promise<ImageProperty[]> { async getPropertyImages(id: string): Promise<string[]> {
return await lastValueFrom(this.http.get<ImageProperty[]>(`${this.apiBaseUrl}/bizmatch/image/${id}`)); return await lastValueFrom(this.http.get<string[]>(`${this.apiBaseUrl}/bizmatch/image/${id}`));
} }
async changeImageOrder(id: string, propertyImages: ImageProperty[]): Promise<ImageProperty[]> { async changeImageOrder(id: string, propertyImages: string[]): Promise<string[]> {
return await lastValueFrom(this.http.put<ImageProperty[]>(`${this.apiBaseUrl}/bizmatch/listings/commercialProperty/imageOrder/${id}`, propertyImages)); return await lastValueFrom(this.http.put<string[]>(`${this.apiBaseUrl}/bizmatch/listings/commercialProperty/imageOrder/${id}`, propertyImages));
} }
} }

View File

@ -4,7 +4,7 @@ import { jwtDecode } from 'jwt-decode';
import { Observable, distinctUntilChanged, filter, from, lastValueFrom, map } from 'rxjs'; import { Observable, distinctUntilChanged, filter, from, lastValueFrom, map } from 'rxjs';
import urlcat from 'urlcat'; import urlcat from 'urlcat';
import { User } from '../../../../bizmatch-server/src/models/db.model'; import { User } from '../../../../bizmatch-server/src/models/db.model';
import { JwtToken, ListingCriteria } from '../../../../bizmatch-server/src/models/main.model'; import { JwtToken, ListingCriteria, ResponseUsersArray } from '../../../../bizmatch-server/src/models/main.model';
import { environment } from '../../environments/environment'; import { environment } from '../../environments/environment';
import { KeycloakService } from './keycloak.service'; import { KeycloakService } from './keycloak.service';
@ -116,7 +116,7 @@ export class UserService {
const url = urlcat(`${this.apiBaseUrl}/bizmatch/user`, { mail }); const url = urlcat(`${this.apiBaseUrl}/bizmatch/user`, { mail });
return await lastValueFrom(this.http.get<User>(url)); return await lastValueFrom(this.http.get<User>(url));
} }
async search(criteria?: ListingCriteria) { async search(criteria?: ListingCriteria): Promise<ResponseUsersArray> {
return await lastValueFrom(this.http.post<User[]>(`${this.apiBaseUrl}/bizmatch/user/search`, criteria)); return await lastValueFrom(this.http.post<ResponseUsersArray>(`${this.apiBaseUrl}/bizmatch/user/search`, criteria));
} }
} }