cleanup + Property images

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

View File

@@ -7,6 +7,7 @@
<p-button icon="pi pi-times" [rounded]="true" severity="danger" (click)="back()"></p-button>
</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="col-12 md:col-6">
<ul class="list-none p-0 m-0 border-top-1 border-300">
@@ -95,6 +96,7 @@
</div>
</div>
</div>
}
</div>
</div>
</div>

View File

@@ -6,7 +6,7 @@ import { MessageService } from 'primeng/api';
import { GalleriaModule } from 'primeng/galleria';
import { lastValueFrom } from 'rxjs';
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 { ListingsService } from '../../../services/listings.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 type: 'business' | 'commercialProperty' | undefined = this.activatedRoute.snapshot.params['type'] as 'business' | 'commercialProperty' | undefined;
listing: BusinessListing;
criteria: ListingCriteria;
mailinfo: MailInfo;
propertyImages: ImageProperty[] = [];
propertyImages: string[] = [];
environment = environment;
user: User;
description: SafeHtml;
@@ -69,7 +68,7 @@ export class DetailsBusinessListingComponent {
}
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.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>
</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="col-12 md:col-6">
<ul class="list-none p-0 m-0 border-top-1 border-300">
@@ -41,7 +42,7 @@
</ul>
<p-galleria [value]="propertyImages" [showIndicators]="true" [showThumbnails]="false" [responsiveOptions]="responsiveOptions" [containerStyle]="{ 'max-width': '640px' }" [numVisible]="5">
<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 pTemplate="thumbnail" let-item>
<div class="grid grid-nogutter justify-content-center">
@@ -85,6 +86,7 @@
</div>
</div>
</div>
}
</div>
</div>
</div>

View File

@@ -6,7 +6,7 @@ import { MessageService } from 'primeng/api';
import { GalleriaModule } from 'primeng/galleria';
import { lastValueFrom } from 'rxjs';
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 { ListingsService } from '../../../services/listings.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 type: 'business' | 'commercialProperty' | undefined = this.activatedRoute.snapshot.params['type'] as 'business' | 'commercialProperty' | undefined;
listing: CommercialPropertyListing;
criteria: ListingCriteria;
mailinfo: MailInfo;
propertyImages: ImageProperty[] = [];
propertyImages: string[] = [];
environment = environment;
user: User;
description: SafeHtml;
@@ -69,7 +68,7 @@ export class DetailsCommercialPropertyListingComponent {
}
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.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description);
}

View File

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

View File

@@ -3,9 +3,9 @@
}
.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/2_1_Version.jpg);
//background-image: url(../../../assets/images/2_1_Version.jpg);
background-size: cover;
background-position: center;
height: 100vh;

View File

@@ -2,7 +2,10 @@
<div class="search">
<div class="wrapper">
<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>
</div>
</div>
@@ -41,7 +44,7 @@
}
</div>
<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>
</div>
</div>

View File

@@ -66,11 +66,17 @@ export class BrokerListingsComponent {
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() {
this.listings = [];
this.filteredListings = [];
this.users = await this.userService.search(this.criteria);
this.search();
}
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 logos = await this.imageService.getCompanyLogosForUsers(this.users.map(u => u.id));
this.users.forEach(u => {
@@ -80,28 +86,12 @@ export class BrokerListingsComponent {
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() {
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) {
this.criteria.start = event.first;
this.criteria.length = event.rows;
this.criteria.page = event.page;
this.criteria.pageCount = event.pageCount;
this.search();
}
imageErrorHandler(listing: ListingType) {
// 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 { StyleClassModule } from 'primeng/styleclass';
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 { environment } from '../../../../environments/environment';
import { ImageService } from '../../../services/image.service';
import { ListingsService } from '../../../services/listings.service';
import { SelectOptionsService } from '../../../services/select-options.service';
import { UserService } from '../../../services/user.service';
import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils';
@Component({
@@ -29,7 +28,6 @@ import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler }
export class BusinessListingsComponent {
environment = environment;
listings: Array<BusinessListing>;
users: Array<User>;
filteredListings: Array<BusinessListing>;
criteria: ListingCriteria;
realEstateChecked: boolean;
@@ -37,7 +35,6 @@ export class BusinessListingsComponent {
minPrice: string;
type: string;
states = [];
statesSet = new Set();
state: string;
first: number = 0;
rows: number = 12;
@@ -48,7 +45,6 @@ export class BusinessListingsComponent {
constructor(
public selectOptions: SelectOptionsService,
private listingsService: ListingsService,
private userService: UserService,
private activatedRoute: ActivatedRoute,
private router: Router,
private cdRef: ChangeDetectorRef,
@@ -68,30 +64,14 @@ export class BusinessListingsComponent {
}
async ngOnInit() {}
async init() {
this.users = [];
this.listings = await this.listingsService.getListings(this.criteria, 'business');
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 }));
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 }));
this.search();
}
async search() {
this.listings = await this.listingsService.getListings(this.criteria, 'business');
this.setStates();
this.totalRecords = this.listings.length;
this.filteredListings = [...this.listings].splice(this.first, this.rows);
const listingReponse = await this.listingsService.getListings(this.criteria, 'business');
this.listings = listingReponse.data;
this.totalRecords = listingReponse.total;
this.cdRef.markForCheck();
this.cdRef.detectChanges();
}
@@ -100,6 +80,7 @@ export class BusinessListingsComponent {
this.criteria.length = event.rows;
this.criteria.page = event.page;
this.criteria.pageCount = event.pageCount;
this.search();
}
imageErrorHandler(listing: ListingType) {
// 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">
<div class="relative">
@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 {
<!-- <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" />

View File

@@ -10,13 +10,12 @@ import { InputTextModule } from 'primeng/inputtext';
import { PaginatorModule } from 'primeng/paginator';
import { StyleClassModule } from 'primeng/styleclass';
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 { environment } from '../../../../environments/environment';
import { ImageService } from '../../../services/image.service';
import { ListingsService } from '../../../services/listings.service';
import { SelectOptionsService } from '../../../services/select-options.service';
import { UserService } from '../../../services/user.service';
import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler } from '../../../utils/utils';
@Component({
@@ -29,7 +28,6 @@ import { createGenericObject, getCriteriaStateObject, getSessionStorageHandler }
export class CommercialPropertyListingsComponent {
environment = environment;
listings: Array<CommercialPropertyListing>;
users: Array<User>;
filteredListings: Array<CommercialPropertyListing>;
criteria: ListingCriteria;
realEstateChecked: boolean;
@@ -48,7 +46,6 @@ export class CommercialPropertyListingsComponent {
constructor(
public selectOptions: SelectOptionsService,
private listingsService: ListingsService,
private userService: UserService,
private activatedRoute: ActivatedRoute,
private router: Router,
private cdRef: ChangeDetectorRef,
@@ -67,41 +64,24 @@ export class CommercialPropertyListingsComponent {
}
async ngOnInit() {}
async init() {
this.users = [];
this.listings = await this.listingsService.getListings(this.criteria, 'commercialProperty');
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 }));
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() {
this.listings = await this.listingsService.getListings(this.criteria, 'commercialProperty');
this.setStates();
this.totalRecords = this.listings.length;
this.filteredListings = [...this.listings].splice(this.first, this.rows);
const listingReponse = await this.listingsService.getListings(this.criteria, 'commercialProperty');
this.listings = listingReponse.data;
this.totalRecords = listingReponse.total;
this.cdRef.markForCheck();
this.cdRef.detectChanges();
}
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.length = event.rows;
this.criteria.page = event.page;
this.criteria.pageCount = event.pageCount;
this.search();
}
imageErrorHandler(listing: ListingType) {
// listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann

View File

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

View File

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

View File

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

View File

@@ -2,7 +2,7 @@ import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, lastValueFrom } from 'rxjs';
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';
@Injectable({
@@ -15,9 +15,9 @@ export class ListingsService {
// getAllListings():Observable<ListingType[]>{
// return this.http.get<ListingType[]>(`${this.apiBaseUrl}/bizmatch/business-listings`);
// }
async getListings(criteria: ListingCriteria, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty'): Promise<ListingType[]> {
const result = await lastValueFrom(this.http.post<ResponseBusinessListingArray>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/search`, criteria));
return result.data;
async getListings(criteria: ListingCriteria, listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty'): Promise<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray> {
const result = await lastValueFrom(this.http.post<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/search`, criteria));
return result;
}
getListingById(id: string, listingsCategory?: 'business' | 'commercialProperty'): Observable<ListingType> {
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));
}
}
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') {
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`));
}
async getPropertyImages(id: string): Promise<ImageProperty[]> {
return await lastValueFrom(this.http.get<ImageProperty[]>(`${this.apiBaseUrl}/bizmatch/image/${id}`));
async getPropertyImages(id: string): Promise<string[]> {
return await lastValueFrom(this.http.get<string[]>(`${this.apiBaseUrl}/bizmatch/image/${id}`));
}
async changeImageOrder(id: string, propertyImages: ImageProperty[]): Promise<ImageProperty[]> {
return await lastValueFrom(this.http.put<ImageProperty[]>(`${this.apiBaseUrl}/bizmatch/listings/commercialProperty/imageOrder/${id}`, propertyImages));
async changeImageOrder(id: string, propertyImages: string[]): Promise<string[]> {
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 urlcat from 'urlcat';
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 { KeycloakService } from './keycloak.service';
@@ -116,7 +116,7 @@ export class UserService {
const url = urlcat(`${this.apiBaseUrl}/bizmatch/user`, { mail });
return await lastValueFrom(this.http.get<User>(url));
}
async search(criteria?: ListingCriteria) {
return await lastValueFrom(this.http.post<User[]>(`${this.apiBaseUrl}/bizmatch/user/search`, criteria));
async search(criteria?: ListingCriteria): Promise<ResponseUsersArray> {
return await lastValueFrom(this.http.post<ResponseUsersArray>(`${this.apiBaseUrl}/bizmatch/user/search`, criteria));
}
}