From 2b27ab8ba56d6067002cc683ed7ae121c9669607 Mon Sep 17 00:00:00 2001 From: Andreas Knuth Date: Sun, 17 Mar 2024 20:29:53 +0100 Subject: [PATCH] Ansichten verbessert - 1. Teil --- bizmatch-server/.gitignore | 2 +- .../src/account/account.controller.ts | 11 ++- bizmatch-server/src/app.module.ts | 2 +- bizmatch-server/src/file/file.service.ts | 50 +++++++++- .../listings/broker-listings.controller.ts | 21 ++++ .../listings/business-listings.controller.ts | 2 +- ...commercial-property-listings.controller.ts | 18 +++- .../src/listings/listings.module.ts | 9 +- .../src/listings/listings.service.ts | 1 + .../listings/unknown-listings.controller.ts | 26 +++++ .../select-options.controller.ts | 1 + .../select-options/select-options.service.ts | 9 ++ bizmatch-server/src/user/user.service.ts | 6 +- .../app/pages/details/details.component.ts | 6 +- .../pages/listings/listings.component.html | 2 +- .../subscription/account/account.component.ts | 8 +- .../edit-listing/edit-listing.component.html | 95 ++++++++++++------- .../edit-listing/edit-listing.component.scss | 9 +- .../edit-listing/edit-listing.component.ts | 62 ++++++++---- .../favorites/favorites.component.ts | 8 +- .../my-listing/my-listing.component.ts | 10 +- bizmatch/src/app/services/listings.service.ts | 35 +++---- .../app/services/select-options.service.ts | 5 +- common-models/src/main.model.ts | 32 ++++--- 24 files changed, 322 insertions(+), 108 deletions(-) create mode 100644 bizmatch-server/src/listings/broker-listings.controller.ts create mode 100644 bizmatch-server/src/listings/unknown-listings.controller.ts diff --git a/bizmatch-server/.gitignore b/bizmatch-server/.gitignore index d07c0ad..422d033 100644 --- a/bizmatch-server/.gitignore +++ b/bizmatch-server/.gitignore @@ -55,4 +55,4 @@ pids # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json -public \ No newline at end of file +pictures \ No newline at end of file diff --git a/bizmatch-server/src/account/account.controller.ts b/bizmatch-server/src/account/account.controller.ts index cd3d35b..9c3e070 100644 --- a/bizmatch-server/src/account/account.controller.ts +++ b/bizmatch-server/src/account/account.controller.ts @@ -6,9 +6,14 @@ import { FileService } from '../file/file.service.js'; export class AccountController { constructor(private fileService:FileService){} - @Post('uploadPhoto/:id') + @Post('uploadProfile/:id') @UseInterceptors(FileInterceptor('file'),) - uploadFile(@UploadedFile() file: Express.Multer.File,@Param('id') id:string) { - this.fileService.storeFile(file,id); + uploadProfile(@UploadedFile() file: Express.Multer.File,@Param('id') id:string) { + this.fileService.storeProfilePicture(file,id); + } + @Post('uploadCompanyLogo/:id') + @UseInterceptors(FileInterceptor('file'),) + uploadCompanyLogo(@UploadedFile() file: Express.Multer.File,@Param('id') id:string) { + this.fileService.storeCompanyLogo(file,id); } } diff --git a/bizmatch-server/src/app.module.ts b/bizmatch-server/src/app.module.ts index 9f36b52..47b5c4e 100644 --- a/bizmatch-server/src/app.module.ts +++ b/bizmatch-server/src/app.module.ts @@ -31,7 +31,7 @@ const __dirname = path.dirname(__filename); @Module({ imports: [ConfigModule.forRoot(), MailModule, AuthModule, ServeStaticModule.forRoot({ - rootPath: join(__dirname, '..', 'public'), // `public` ist das Verzeichnis, wo Ihre statischen Dateien liegen + rootPath: join(__dirname, '..', 'pictures'), // `public` ist das Verzeichnis, wo Ihre statischen Dateien liegen }), WinstonModule.forRoot({ transports: [ diff --git a/bizmatch-server/src/file/file.service.ts b/bizmatch-server/src/file/file.service.ts index 9ea8da9..4e00371 100644 --- a/bizmatch-server/src/file/file.service.ts +++ b/bizmatch-server/src/file/file.service.ts @@ -4,6 +4,7 @@ import { join } from 'path'; import { fileURLToPath } from 'url'; import path from 'path'; import fs from 'fs-extra'; +import { ImageProperty } from 'src/models/main.model.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -13,6 +14,10 @@ export class FileService { private subscriptions: any; constructor() { this.loadSubscriptions(); + fs.ensureDirSync(`./pictures`); + fs.ensureDirSync(`./pictures/profile`); + fs.ensureDirSync(`./pictures/logo`); + fs.ensureDirSync(`./pictures/property`); } private loadSubscriptions(): void { const filePath = join(__dirname,'..', 'assets', 'subscriptions.json'); @@ -22,8 +27,49 @@ export class FileService { getSubscriptions() { return this.subscriptions } - async storeFile(file: Express.Multer.File,id: string){ + async storeProfilePicture(file: Express.Multer.File,userId: string){ const suffix = file.mimetype.includes('png')?'png':'jpg' - await fs.outputFile(`./public/profile_${id}`,file.buffer); + await fs.outputFile(`./pictures/profile/${userId}`,file.buffer); + } + async storeCompanyLogo(file: Express.Multer.File,userId: string){ + const suffix = file.mimetype.includes('png')?'png':'jpg' + await fs.outputFile(`./pictures/logo/${userId}`,file.buffer); + } + async getPropertyImages(listingId: string):Promise{ + const result:ImageProperty[]=[] + const directory = `./pictures/property/${listingId}` + if (fs.existsSync(directory)){ + const files = await fs.readdir(directory); + files.forEach(f=>{ + const image:ImageProperty={name:f,id:'',code:''}; + result.push(image) + }) + return result; + } else { + return [] + } + + } + async storePropertyPicture(file: Express.Multer.File,listingId: string){ + const suffix = file.mimetype.includes('png')?'png':'jpg' + const directory = `./pictures/property/${listingId}` + fs.ensureDirSync(`${directory}`); + const imageName = await this.getNextImageName(directory); + await fs.outputFile(`${directory}/${imageName}`,file.buffer); + } + async getNextImageName(directory) { + try { + const files = await fs.readdir(directory); + const imageNumbers = files + .map(file => parseInt(file, 10)) // Dateinamen direkt in Zahlen umwandeln + .filter(number => !isNaN(number)) // Sicherstellen, dass die Konvertierung gültig ist + .sort((a, b) => a - b); // Aufsteigend sortieren + + const nextNumber = imageNumbers.length > 0 ? Math.max(...imageNumbers) + 1 : 1; + return `${nextNumber}`; // Keine Endung für den Dateinamen + } catch (error) { + console.error('Fehler beim Lesen des Verzeichnisses:', error); + return null; + } } } diff --git a/bizmatch-server/src/listings/broker-listings.controller.ts b/bizmatch-server/src/listings/broker-listings.controller.ts new file mode 100644 index 0000000..f04034c --- /dev/null +++ b/bizmatch-server/src/listings/broker-listings.controller.ts @@ -0,0 +1,21 @@ +import { Body, Controller, Delete, Get, Inject, Param, Post, Put } from '@nestjs/common'; +import { FileService } from '../file/file.service.js'; +import { convertStringToNullUndefined } from '../utils.js'; +import { ListingsService } from './listings.service.js'; +import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; +import { Logger } from 'winston'; +import { UserService } from '../user/user.service.js'; + +@Controller('listings/professionals_brokers') +export class BrokerListingsController { + + constructor(private readonly userService:UserService,@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) { + } + + @Post('search') + find(@Body() criteria: any): any { + return this.userService.findUser(criteria); + } + +} + diff --git a/bizmatch-server/src/listings/business-listings.controller.ts b/bizmatch-server/src/listings/business-listings.controller.ts index 76d733a..9926c69 100644 --- a/bizmatch-server/src/listings/business-listings.controller.ts +++ b/bizmatch-server/src/listings/business-listings.controller.ts @@ -5,7 +5,7 @@ import { ListingsService } from './listings.service.js'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; -@Controller('business-listings') +@Controller('listings/business') export class BusinessListingsController { constructor(private readonly listingsService:ListingsService,@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) { diff --git a/bizmatch-server/src/listings/commercial-property-listings.controller.ts b/bizmatch-server/src/listings/commercial-property-listings.controller.ts index 625c820..9ce561f 100644 --- a/bizmatch-server/src/listings/commercial-property-listings.controller.ts +++ b/bizmatch-server/src/listings/commercial-property-listings.controller.ts @@ -1,12 +1,14 @@ -import { Body, Controller, Delete, Get, Inject, Param, Post } from '@nestjs/common'; +import { Body, Controller, Delete, Get, Inject, Param, Post, UploadedFile, UseInterceptors } from '@nestjs/common'; import { ListingsService } from './listings.service.js'; import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; import { Logger } from 'winston'; +import { FileInterceptor } from '@nestjs/platform-express'; +import { FileService } from '../file/file.service.js'; -@Controller('commercial-property-listings') +@Controller('listings/commercialProperty') export class CommercialPropertyListingsController { - constructor(private readonly listingsService:ListingsService,@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) { + constructor(private readonly listingsService:ListingsService,private fileService:FileService,@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) { } @Get() @@ -40,5 +42,15 @@ export class CommercialPropertyListingsController { deleteById(@Param('id') id:string){ this.listingsService.deleteCommercialPropertyListing(id) } + + @Post('uploadPropertyPicture/:id') + @UseInterceptors(FileInterceptor('file'),) + uploadFile(@UploadedFile() file: Express.Multer.File,@Param('id') id:string) { + this.fileService.storePropertyPicture(file,id); + } + @Get('images/:id') + getPropertyImagesById(@Param('id') id:string): any { + return this.fileService.getPropertyImages(id); + } } diff --git a/bizmatch-server/src/listings/listings.module.ts b/bizmatch-server/src/listings/listings.module.ts index 1cb3b21..1bb5da1 100644 --- a/bizmatch-server/src/listings/listings.module.ts +++ b/bizmatch-server/src/listings/listings.module.ts @@ -3,10 +3,15 @@ import { BusinessListingsController } from './business-listings.controller.js'; import { ListingsService } from './listings.service.js'; import { CommercialPropertyListingsController } from './commercial-property-listings.controller.js'; import { RedisModule } from '../redis/redis.module.js'; +import { FileService } from '../file/file.service.js'; +import { UnknownListingsController } from './unknown-listings.controller.js'; +import { UserModule } from '../user/user.module.js'; +import { BrokerListingsController } from './broker-listings.controller.js'; +import { UserService } from '../user/user.service.js'; @Module({ imports: [RedisModule], - controllers: [BusinessListingsController, CommercialPropertyListingsController], - providers: [ListingsService] + controllers: [BusinessListingsController, CommercialPropertyListingsController,UnknownListingsController,BrokerListingsController], + providers: [ListingsService,FileService,UserService] }) export class ListingsModule {} diff --git a/bizmatch-server/src/listings/listings.service.ts b/bizmatch-server/src/listings/listings.service.ts index 77bd01e..6943693 100644 --- a/bizmatch-server/src/listings/listings.service.ts +++ b/bizmatch-server/src/listings/listings.service.ts @@ -67,6 +67,7 @@ export class ListingsService { async saveListing(listing: BusinessListing | CommercialPropertyListing) { const repo=listing.listingsCategory==='business'?this.businessListingRepository:this.commercialPropertyListingRepository; let result + listing.temporary=false; if (listing.id){ result = await repo.save(listing.id,listing as any) } else { diff --git a/bizmatch-server/src/listings/unknown-listings.controller.ts b/bizmatch-server/src/listings/unknown-listings.controller.ts new file mode 100644 index 0000000..7879a26 --- /dev/null +++ b/bizmatch-server/src/listings/unknown-listings.controller.ts @@ -0,0 +1,26 @@ +import { Body, Controller, Delete, Get, Inject, Param, Post, Put } from '@nestjs/common'; +import { FileService } from '../file/file.service.js'; +import { convertStringToNullUndefined } from '../utils.js'; +import { ListingsService } from './listings.service.js'; +import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; +import { Logger } from 'winston'; + +@Controller('listings/undefined') +export class UnknownListingsController { + + constructor(private readonly listingsService:ListingsService,@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) { + } + + + @Get(':id') + async findById(@Param('id') id:string): Promise { + const result = await this.listingsService.getBusinessListingById(id); + if (result.id){ + return result + } else { + return await this.listingsService.getCommercialPropertyListingById(id); + } + } + +} + diff --git a/bizmatch-server/src/select-options/select-options.controller.ts b/bizmatch-server/src/select-options/select-options.controller.ts index 42a1b75..f37d8d3 100644 --- a/bizmatch-server/src/select-options/select-options.controller.ts +++ b/bizmatch-server/src/select-options/select-options.controller.ts @@ -12,6 +12,7 @@ export class SelectOptionsController { listingCategories:this.selectOptionsService.listingCategories, categories:this.selectOptionsService.categories, locations:this.selectOptionsService.locations, + typesOfCommercialProperty:this.selectOptionsService.typesOfCommercialProperty, } } } diff --git a/bizmatch-server/src/select-options/select-options.service.ts b/bizmatch-server/src/select-options/select-options.service.ts index 6013d01..e8bfaf2 100644 --- a/bizmatch-server/src/select-options/select-options.service.ts +++ b/bizmatch-server/src/select-options/select-options.service.ts @@ -20,6 +20,15 @@ export class SelectOptionsService { { name: 'Manufacturing', value: '12' , icon:'fa-solid fa-industry',bgColorClass:'bg-red-100',textColorClass:'text-red-600'}, { name: 'Food and Restaurant', value: '13' , icon:'fa-solid fa-utensils',bgColorClass:'bg-primary-100',textColorClass:'text-primary-600'}, ]; + public typesOfCommercialProperty: Array = [ + { name: 'Retail', value: '100' , icon:'fa-solid fa-money-bill-wave',bgColorClass:'bg-pink-100',textColorClass:'text-pink-600'}, + { name: 'Land', value: '101' , icon:'pi pi-building',bgColorClass:'bg-blue-100',textColorClass:'text-blue-600'}, + { name: 'Industrial', value: '102', icon:'fa-solid fa-industry',bgColorClass:'bg-yellow-100',textColorClass:'text-yellow-600'}, + { name: 'Office', value: '103' , icon:'fa-solid fa-umbrella',bgColorClass:'bg-teal-100',textColorClass:'text-teal-600'}, + { name: 'Mixed Use', value: '104' , icon:'fa-solid fa-rectangle-ad',bgColorClass:'bg-orange-100',textColorClass:'text-orange-600'}, + { name: 'Multifamily', value: '105' , icon:'pi pi-star',bgColorClass:'bg-purple-100',textColorClass:'text-purple-600'}, + { name: 'Uncategorized', value: '106' , icon:'pi pi-question',bgColorClass:'bg-cyan-100',textColorClass:'text-cyan-600'}, + ]; public prices: Array = [ { name: '$100K', value: '100000' }, { name: '$250K', value: '250000' }, diff --git a/bizmatch-server/src/user/user.service.ts b/bizmatch-server/src/user/user.service.ts index c5d0563..1ef5a58 100644 --- a/bizmatch-server/src/user/user.service.ts +++ b/bizmatch-server/src/user/user.service.ts @@ -1,7 +1,7 @@ import { Get, Inject, Injectable, Param } from '@nestjs/common'; import { createClient } from 'redis'; import { Entity, Repository, Schema } from 'redis-om'; -import { User } from '../models/main.model.js'; +import { ListingCriteria, User } from '../models/main.model.js'; import { REDIS_CLIENT } from '../redis/redis.module.js'; import { UserEntity } from '../models/server.model.js'; @@ -26,6 +26,7 @@ export class UserService { }) constructor(@Inject(REDIS_CLIENT) private readonly redis: any){ this.userRepository = new Repository(this.userSchema, redis) + this.userRepository.createIndex(); } async getUserById( id:string){ return await this.userRepository.fetch(id); @@ -33,5 +34,8 @@ export class UserService { async saveUser(user:any):Promise{ return await this.userRepository.save(user.id,user) as UserEntity } + async findUser(criteria:ListingCriteria){ + return await this.userRepository.search().return.all(); + } } \ No newline at end of file diff --git a/bizmatch/src/app/pages/details/details.component.ts b/bizmatch/src/app/pages/details/details.component.ts index f1392c5..c5adaa7 100644 --- a/bizmatch/src/app/pages/details/details.component.ts +++ b/bizmatch/src/app/pages/details/details.component.ts @@ -51,8 +51,10 @@ export class DetailsComponent { } async ngOnInit(){ - this.user = this.userService.getUser(); - this.listing=await lastValueFrom(this.listingsService.getListingById(this.id)); + this.userService.getUserObservable().subscribe(user=>{ + this.user=user + }); + this.listing=await lastValueFrom(this.listingsService.getListingById(this.id,this.criteria.listingsCategory)); } back(){ this.router.navigate(['listings',this.criteria.listingsCategory]) diff --git a/bizmatch/src/app/pages/listings/listings.component.html b/bizmatch/src/app/pages/listings/listings.component.html index ac324de..5c2ec19 100644 --- a/bizmatch/src/app/pages/listings/listings.component.html +++ b/bizmatch/src/app/pages/listings/listings.component.html @@ -95,7 +95,7 @@

Phone Number: {{listing.phoneNumber}}

--> }
- +
diff --git a/bizmatch/src/app/pages/subscription/account/account.component.ts b/bizmatch/src/app/pages/subscription/account/account.component.ts index ed5b8bd..a333c67 100644 --- a/bizmatch/src/app/pages/subscription/account/account.component.ts +++ b/bizmatch/src/app/pages/subscription/account/account.component.ts @@ -55,8 +55,8 @@ export class AccountComponent { } async ngOnInit(){ - this.profileUrl = `${environment.apiBaseUrl}/profile_${this.user.id}` - this.companyLogoUrl = `${environment.apiBaseUrl}/profile_${this.user.id}` + this.profileUrl = `${environment.apiBaseUrl}/profile/${this.user.id}` + this.companyLogoUrl = `${environment.apiBaseUrl}/logo/${this.user.id}` this.userSubscriptions=await lastValueFrom(this.subscriptionService.getAllSubscriptions()); this.uploadUrl = `${environment.apiBaseUrl}/bizmatch/account/uploadPhoto/${this.user.id}`; if (!this.user.licensedIn || this.user.licensedIn?.length===0){ @@ -74,11 +74,11 @@ export class AccountComponent { onUploadCompanyLogo(event:any){ const uniqueSuffix = '?_ts=' + new Date().getTime(); - this.companyLogoUrl = `${environment.apiBaseUrl}/company_${this.user.id}${uniqueSuffix}` //`http://IhrServer:Port/${newImagePath}${uniqueSuffix}`; + this.companyLogoUrl = `${environment.apiBaseUrl}/company/${this.user.id}${uniqueSuffix}` //`http://IhrServer:Port/${newImagePath}${uniqueSuffix}`; } onUploadProfilePicture(event:any){ const uniqueSuffix = '?_ts=' + new Date().getTime(); - this.profileUrl = `${environment.apiBaseUrl}/profile_${this.user.id}${uniqueSuffix}` //`http://IhrServer:Port/${newImagePath}${uniqueSuffix}`; + this.profileUrl = `${environment.apiBaseUrl}/profile/${this.user.id}${uniqueSuffix}` //`http://IhrServer:Port/${newImagePath}${uniqueSuffix}`; } setImageToFallback(event: Event) { (event.target as HTMLImageElement).src = `/assets/images/placeholder.png`; // Pfad zum Platzhalterbild diff --git a/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.html b/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.html index 1c45bde..0a7d9b1 100644 --- a/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.html +++ b/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.html @@ -26,52 +26,83 @@
@if (listing.listingsCategory==='business'){
- - Type of business +
} + @if (listing.listingsCategory==='commercialProperty'){ +
+ + +
+ }
-
- - -
-
- - - -
-
- + }
+ @if (listing.listingsCategory==='commercialProperty'){ +
+
+ + + +
+
+
+ Property Picture + + +
+
+
+ + +
+
+ +
+ +
+
+
+ } @if (listing.listingsCategory==='business'){
diff --git a/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.scss b/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.scss index 4f09e5c..a4111ab 100644 --- a/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.scss +++ b/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.scss @@ -1,3 +1,10 @@ .translate-y-5{ transform: translateY(5px); -} \ No newline at end of file +} +.image { + width: 120px; + height: 30px; + border: 1px solid #6b7280; + padding: 1px 1px; + object-fit: contain; + } \ No newline at end of file diff --git a/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.ts b/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.ts index 12988c1..aee5db4 100644 --- a/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.ts +++ b/bizmatch/src/app/pages/subscription/edit-listing/edit-listing.component.ts @@ -25,16 +25,18 @@ import { ArrayToStringPipe } from '../../../pipes/array-to-string.pipe'; import { UserService } from '../../../services/user.service'; import { SharedModule } from '../../../shared/shared/shared.module'; import { MessageService } from 'primeng/api'; -import { AutoCompleteCompleteEvent, BusinessListing, ListingType, User } from '../../../../../../common-models/src/main.model'; +import { AutoCompleteCompleteEvent, BusinessListing, CommercialPropertyListing, ImageProperty, ListingType, User } from '../../../../../../common-models/src/main.model'; import { GeoResult, GeoService } from '../../../services/geo.service'; import { InputNumberComponent, InputNumberModule } from '../../../components/inputnumber/inputnumber.component'; - - +import { environment } from '../../../../environments/environment'; +import { FileUploadModule } from 'primeng/fileupload'; +import { CarouselModule } from 'primeng/carousel'; +import { v4 as uuidv4 } from 'uuid'; @Component({ selector: 'create-listing', standalone: true, - imports: [SharedModule,ArrayToStringPipe, InputNumberModule], + imports: [SharedModule,ArrayToStringPipe, InputNumberModule,FileUploadModule,CarouselModule], providers:[MessageService], templateUrl: './edit-listing.component.html', styleUrl: './edit-listing.component.scss' @@ -45,10 +47,30 @@ export class EditListingComponent { location:string; mode:'edit'|'create'; separator:'\n\n' - listing:ListingType = createGenericObject(); + listing:ListingType private id: string | undefined = this.activatedRoute.snapshot.params['id'] as string | undefined; user:User; - value:12; + maxFileSize=1000000; + uploadUrl:string; + environment=environment; + propertyImages:ImageProperty[] + responsiveOptions = [ + { + breakpoint: '1199px', + numVisible: 1, + numScroll: 1 + }, + { + breakpoint: '991px', + numVisible: 2, + numScroll: 1 + }, + { + breakpoint: '767px', + numVisible: 1, + numScroll: 1 + } +]; constructor(public selectOptions:SelectOptionsService, private router: Router, private activatedRoute: ActivatedRoute, @@ -68,23 +90,21 @@ export class EditListingComponent { async ngOnInit(){ if (this.mode==='edit'){ this.listing=await lastValueFrom(this.listingsService.getListingById(this.id)); - this.listing.price=123456 } else { + const uuid = sessionStorage.getItem('uuid')?sessionStorage.getItem('uuid'):uuidv4(); + sessionStorage.setItem('uuid',uuid); this.listing=createGenericObject(); + this.listing.id=uuid + this.listing.temporary=true; this.listing.userId=this.user.id this.listing.listingsCategory='business'; } + this.uploadUrl = `${environment.apiBaseUrl}/bizmatch/${this.listing.listingsCategory}/uploadPropertyPicture/${this.listing.id}`; + this.propertyImages=await this.listingsService.getPropertyImages(this.listing.id) } - // updateSummary(value: string): void { - // const lines = value.split('\n'); - // (this.listing).summary = lines.filter(l=>l.trim().length>0); - // } - // async update(id:string){ - // await this.listingsService.update(this.listing,this.listing.id); - // this.messageService.add({ severity: 'info', summary: 'Confirmed', detail: 'Listing has been updated', life: 3000 }); - // } async save(){ - await this.listingsService.save(this.listing); + sessionStorage.removeItem('uuid') + await this.listingsService.save(this.listing,this.listing.listingsCategory); this.messageService.add({ severity: 'info', summary: 'Confirmed', detail: 'Listing changes have been persisted', life: 3000 }); } @@ -94,4 +114,14 @@ export class EditListingComponent { const result = await lastValueFrom(this.geoService.findCitiesStartingWith(event.query,this.listing.state)) this.suggestions = result.map(r=>r.city).slice(0,5); } + + setImageToFallback(event: Event) { + (event.target as HTMLImageElement).src = `/assets/images/placeholder.png`; // Pfad zum Platzhalterbild + } + async onUploadPropertyPicture(event:any){ + // (this.listing).images=[]; + // (this.listing).images.push(this.listing.id); + // await this.listingsService.save(this.listing) + this.propertyImages=await this.listingsService.getPropertyImages(this.listing.id) + } } diff --git a/bizmatch/src/app/pages/subscription/favorites/favorites.component.ts b/bizmatch/src/app/pages/subscription/favorites/favorites.component.ts index 2e5dfe2..f381832 100644 --- a/bizmatch/src/app/pages/subscription/favorites/favorites.component.ts +++ b/bizmatch/src/app/pages/subscription/favorites/favorites.component.ts @@ -6,7 +6,7 @@ import { UserService } from '../../../services/user.service'; import { lastValueFrom } from 'rxjs'; import { ListingsService } from '../../../services/listings.service'; import { SelectOptionsService } from '../../../services/select-options.service'; -import { BusinessListing, User } from '../../../../../../common-models/src/main.model'; +import { BusinessListing, ListingType, User } from '../../../../../../common-models/src/main.model'; @Component({ selector: 'app-favorites', @@ -17,13 +17,13 @@ import { BusinessListing, User } from '../../../../../../common-models/src/main. }) export class FavoritesComponent { user: User; - listings: Array //= dataListings as unknown as Array; - favorites: Array + listings: Array =[]//= dataListings as unknown as Array; + favorites: Array constructor(public userService: UserService, private listingsService:ListingsService, public selectOptions:SelectOptionsService){ this.user=this.userService.getUser(); } async ngOnInit(){ - this.listings=await lastValueFrom(this.listingsService.getAllListings()); + // this.listings=await lastValueFrom(this.listingsService.getAllListings()); this.favorites=this.listings.filter(l=>l.favoritesForUser?.includes(this.user.id)); } } diff --git a/bizmatch/src/app/pages/subscription/my-listing/my-listing.component.ts b/bizmatch/src/app/pages/subscription/my-listing/my-listing.component.ts index 3dec17d..064bb5e 100644 --- a/bizmatch/src/app/pages/subscription/my-listing/my-listing.component.ts +++ b/bizmatch/src/app/pages/subscription/my-listing/my-listing.component.ts @@ -18,20 +18,20 @@ import { BusinessListing, ListingType, User } from '../../../../../../common-mod }) export class MyListingComponent { user: User; - listings: Array //dataListings as unknown as Array; - myListings: Array + listings: Array =[]//dataListings as unknown as Array; + myListings: Array constructor(public userService: UserService,private listingsService:ListingsService, private cdRef:ChangeDetectorRef,public selectOptions:SelectOptionsService,private confirmationService: ConfirmationService,private messageService: MessageService){ this.user=this.userService.getUser(); } async ngOnInit(){ - this.listings=await lastValueFrom(this.listingsService.getAllListings()); + // this.listings=await lastValueFrom(this.listingsService.getAllListings()); this.myListings=this.listings.filter(l=>l.userId===this.user.id); } async deleteListing(listing:ListingType){ - await this.listingsService.deleteListing(listing.id); - this.listings=await lastValueFrom(this.listingsService.getAllListings()); + await this.listingsService.deleteListing(listing.id,listing.listingsCategory); + // this.listings=await lastValueFrom(this.listingsService.getAllListings()); this.myListings=this.listings.filter(l=>l.userId===this.user.id); } diff --git a/bizmatch/src/app/services/listings.service.ts b/bizmatch/src/app/services/listings.service.ts index 6bb50e8..8d1b2b6 100644 --- a/bizmatch/src/app/services/listings.service.ts +++ b/bizmatch/src/app/services/listings.service.ts @@ -2,32 +2,35 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable, lastValueFrom } from 'rxjs'; import { environment } from '../../environments/environment'; -import { BusinessListing, ListingCriteria } from '../../../../common-models/src/main.model'; +import { BusinessListing, ImageProperty, ListingCriteria, ListingType } from '../../../../common-models/src/main.model'; +import onChange from 'on-change'; +import { getSessionStorageHandler } from '../utils/utils'; @Injectable({ providedIn: 'root' }) export class ListingsService { private apiBaseUrl = environment.apiBaseUrl; - constructor(private http: HttpClient) { } - - getAllListings():Observable{ - return this.http.get(`${this.apiBaseUrl}/bizmatch/business-listings`); + constructor(private http: HttpClient) { } - async getListings(criteria:ListingCriteria):Promise{ - const result = await lastValueFrom(this.http.post(`${this.apiBaseUrl}/bizmatch/business-listings/search`,criteria)); + + // getAllListings():Observable{ + // return this.http.get(`${this.apiBaseUrl}/bizmatch/business-listings`); + // } + async getListings(criteria:ListingCriteria):Promise{ + const result = await lastValueFrom(this.http.post(`${this.apiBaseUrl}/bizmatch/listings/${criteria.listingsCategory}/search`,criteria)); return result; } - getListingById(id:string):Observable{ - return this.http.get(`${this.apiBaseUrl}/bizmatch/business-listings/${id}`); + getListingById(id:string,listingsCategory?:'business'|'professionals_brokers'|'commercialProperty'):Observable{ + return this.http.get(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`); } - // async update(listing:any,id:string){ - // await lastValueFrom(this.http.put(`${this.apiBaseUrl}/bizmatch/listings/${id}`,listing)); - // } - async save(listing:any){ - await lastValueFrom(this.http.post(`${this.apiBaseUrl}/bizmatch/business-listings`,listing)); + async save(listing:any,listingsCategory:'business'|'professionals_brokers'|'commercialProperty'){ + await lastValueFrom(this.http.post(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}`,listing)); } - async deleteListing(id:string){ - await lastValueFrom(this.http.delete(`${this.apiBaseUrl}/bizmatch/business-listings/${id}`)); + async deleteListing(id:string,listingsCategory:'business'|'professionals_brokers'|'commercialProperty'){ + await lastValueFrom(this.http.delete(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`)); + } + async getPropertyImages(id:string):Promise{ + return await lastValueFrom(this.http.get(`${this.apiBaseUrl}/bizmatch/listings/commercialProperty/images/${id}`)); } } diff --git a/bizmatch/src/app/services/select-options.service.ts b/bizmatch/src/app/services/select-options.service.ts index f27404a..c90c924 100644 --- a/bizmatch/src/app/services/select-options.service.ts +++ b/bizmatch/src/app/services/select-options.service.ts @@ -21,9 +21,12 @@ export class SelectOptionsService { this.listingCategories = allSelectOptions.listingCategories; this.categories = allSelectOptions.categories; this.states = allSelectOptions.locations; + this.typesOfCommercialProperty = allSelectOptions.typesOfCommercialProperty } public typesOfBusiness: Array; - + + public typesOfCommercialProperty: Array; + public prices: Array; public listingCategories: Array; diff --git a/common-models/src/main.model.ts b/common-models/src/main.model.ts index 7cfbd2c..65a4352 100644 --- a/common-models/src/main.model.ts +++ b/common-models/src/main.model.ts @@ -16,22 +16,23 @@ export type SelectOption = { export interface Listing { id: string; userId: string; + type: string; //enum title: string; description: Array; country: string; city: string, state: string;//enum + price?: number; favoritesForUser:Array; hideImage?:boolean; draft?:boolean; created:Date; updated:Date; + temporary:boolean; } export interface BusinessListing extends Listing { listingsCategory: 'business'; //enum // summary: Array; - type: string; //enum - price?: number; realEstateIncluded?: boolean; leasedLocation?:boolean; franchiseResale?:boolean; @@ -46,6 +47,18 @@ export interface BusinessListing extends Listing { brokerLicencing?: string; internals?: string; } +export interface CommercialPropertyListing extends Listing { + listingsCategory: 'commercialProperty'; //enum + images:string[]; + zipCode:number; + county:string + email?: string; + website?: string; + phoneNumber?: string; +} +export type ListingType = + | BusinessListing + | CommercialPropertyListing; // export interface ProfessionalsBrokersListing extends Listing { // listingsCategory: 'professionals_brokers'; //enum // summary: string; @@ -54,16 +67,6 @@ export interface BusinessListing extends Listing { // website?: string; // category?: 'Professionals' | 'Broker'; // } -export interface CommercialPropertyListing extends Listing { - listingsCategory: 'commercialProperty'; //enum - email?: string; - website?: string; - phoneNumber?: string; -} -export type ListingType = - | BusinessListing - | CommercialPropertyListing; - export interface ListingCriteria { type:string, state:string, @@ -176,4 +179,9 @@ export interface MailInfo { phoneNumber?: string; state?: string; comments?: string; + } + export interface ImageProperty { + id:string; + code:string; + name:string; } \ No newline at end of file