BugFixes:141,140,139,138,137,129

This commit is contained in:
Andreas Knuth 2025-03-19 17:37:33 +01:00
parent cfddabbfe0
commit 923040f487
11 changed files with 83 additions and 41 deletions

View File

@ -68,9 +68,9 @@
<li> <li>
<a routerLink="/account" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Account</a> <a routerLink="/account" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">Account</a>
</li> </li>
@if(user.customerType==='professional' || user.customerType==='seller' || (authService.isAdmin() | async)){ @if((user.customerType==='professional' && user.customerSubType==='broker') || user.customerType==='seller' || (authService.isAdmin() | async)){
<li> <li>
@if(user.customerSubType==='broker'){ @if(user.customerType==='professional'){
<a routerLink="/createBusinessListing" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white" <a routerLink="/createBusinessListing" (click)="closeDropdown()" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
>Create Listing</a >Create Listing</a
> >

View File

@ -394,7 +394,7 @@
[items]="counties$ | async" [items]="counties$ | async"
bindLabel="name" bindLabel="name"
class="custom" class="custom"
[multiple]="false" [multiple]="true"
[hideSelected]="true" [hideSelected]="true"
[trackByFn]="trackByFn" [trackByFn]="trackByFn"
[minTermLength]="2" [minTermLength]="2"

View File

@ -14,13 +14,17 @@
<p class="mb-4" [innerHTML]="description"></p> <p class="mb-4" [innerHTML]="description"></p>
<div class="space-y-2"> <div class="space-y-2">
<div class="flex flex-col sm:flex-row" [ngClass]="{ 'bg-gray-100': i % 2 === 0 }" *ngFor="let item of listingDetails; let i = index"> <div *ngFor="let detail of listingDetails; let i = index" class="flex flex-col sm:flex-row" [ngClass]="{ 'bg-gray-100': i % 2 === 0 }">
<div class="w-full sm:w-1/3 font-semibold p-2">{{ item.label }}</div> <div class="w-full sm:w-1/3 font-semibold p-2">{{ detail.label }}</div>
@if(item.label==='Category'){
<span class="bg-blue-100 text-blue-800 font-medium me-2 px-2.5 py-0.5 rounded-full dark:bg-blue-900 dark:text-blue-300 my-1">{{ item.value }}</span> <div class="w-full sm:w-2/3 p-2" *ngIf="!detail.isHtml && !detail.isListingBy">{{ detail.value }}</div>
} @else {
<div class="w-full sm:w-2/3 p-2">{{ item.value }}</div> <div class="w-full sm:w-2/3 p-2 flex space-x-2" [innerHTML]="detail.value" *ngIf="detail.isHtml && !detail.isListingBy"></div>
}
<div class="w-full sm:w-2/3 p-2 flex space-x-2" *ngIf="detail.isListingBy">
<a routerLink="/details-user/{{ listingUser.id }}" class="text-blue-600 dark:text-blue-500 hover:underline">{{ listingUser.firstname }} {{ listingUser.lastname }}</a>
<img src="{{ env.imageBaseUrl }}/pictures/logo/{{ listing.imageName }}.avif?_ts={{ ts }}" class="mr-5 lg:mb-0" style="max-height: 30px; max-width: 100px" />
</div>
</div> </div>
</div> </div>
<div class="py-4 print:hidden"> <div class="py-4 print:hidden">
@ -84,17 +88,6 @@
<div> <div>
<app-validated-textarea label="Questions/Comments" name="comments" [(ngModel)]="mailinfo.sender.comments"></app-validated-textarea> <app-validated-textarea label="Questions/Comments" name="comments" [(ngModel)]="mailinfo.sender.comments"></app-validated-textarea>
</div> </div>
@if(listingUser){
<div class="flex items-center space-x-2">
<p>Listing by</p>
<!-- <p class="text-sm font-semibold">Noah Nguyen</p> -->
<a routerLink="/details-user/{{ listingUser.id }}" class="text-blue-600 dark:text-blue-500 hover:underline">{{ listingUser.firstname }} {{ listingUser.lastname }}</a>
<!-- <img src="https://placehold.co/20x20" alt="Broker logo" class="w-5 h-5" /> -->
@if(listingUser.hasCompanyLogo){
<img src="{{ env.imageBaseUrl }}/pictures/logo/{{ listing.imageName }}.avif?_ts={{ ts }}" class="mr-5 lg:mb-0" style="max-height: 30px; max-width: 100px" />
}
</div>
}
<button (click)="mail()" class="w-full sm:w-auto px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50">Submit</button> <button (click)="mail()" class="w-full sm:w-auto px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50">Submit</button>
</form> </form>
</div> </div>

View File

@ -159,6 +159,16 @@ export class DetailsBusinessListingComponent extends BaseDetailsComponent {
{ label: 'Reason for Sale', value: this.listing.reasonForSale }, { label: 'Reason for Sale', value: this.listing.reasonForSale },
{ label: 'Broker licensing', value: this.listing.brokerLicencing }, { label: 'Broker licensing', value: this.listing.brokerLicencing },
{ label: 'Listed since', value: `${this.dateInserted()} - ${this.getDaysListed()} days` }, { label: 'Listed since', value: `${this.dateInserted()} - ${this.getDaysListed()} days` },
{
label: 'Listing by',
value: null, // Wird nicht verwendet
isHtml: true,
isListingBy: true, // Flag für den speziellen Fall
user: this.listingUser, // Übergebe das User-Objekt
imagePath: this.listing.imageName,
imageBaseUrl: this.env.imageBaseUrl,
ts: this.ts,
},
]; ];
if (this.listing.draft) { if (this.listing.draft) {
result.push({ label: 'Draft', value: this.listing.draft ? 'Yes' : 'No' }); result.push({ label: 'Draft', value: this.listing.draft ? 'Yes' : 'No' });

View File

@ -16,7 +16,18 @@
<div class="space-y-2"> <div class="space-y-2">
<div *ngFor="let detail of propertyDetails; let i = index" class="flex flex-col sm:flex-row" [ngClass]="{ 'bg-gray-100': i % 2 === 0 }"> <div *ngFor="let detail of propertyDetails; let i = index" class="flex flex-col sm:flex-row" [ngClass]="{ 'bg-gray-100': i % 2 === 0 }">
<div class="w-full sm:w-1/3 font-semibold p-2">{{ detail.label }}</div> <div class="w-full sm:w-1/3 font-semibold p-2">{{ detail.label }}</div>
<div class="w-full sm:w-2/3 p-2">{{ detail.value }}</div>
<!-- Standard Text -->
<div class="w-full sm:w-2/3 p-2" *ngIf="!detail.isHtml && !detail.isListingBy">{{ detail.value }}</div>
<!-- HTML Content (nicht für RouterLink) -->
<div class="w-full sm:w-2/3 p-2 flex space-x-2" [innerHTML]="detail.value" *ngIf="detail.isHtml && !detail.isListingBy"></div>
<!-- Speziell für Listing By mit RouterLink -->
<div class="w-full sm:w-2/3 p-2 flex space-x-2" *ngIf="detail.isListingBy">
<a [routerLink]="['/details-user', detail.user.id]" class="text-blue-600 dark:text-blue-500 hover:underline"> {{ detail.user.firstname }} {{ detail.user.lastname }} </a>
<img *ngIf="detail.user.hasCompanyLogo" [src]="detail.imageBaseUrl + '/pictures/logo/' + detail.imagePath + '.avif?_ts=' + detail.ts" class="mr-5 lg:mb-0" style="max-height: 30px; max-width: 100px" />
</div>
</div> </div>
</div> </div>
<div class="py-4 print:hidden"> <div class="py-4 print:hidden">
@ -88,15 +99,6 @@
</div> </div>
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
@if(listingUser){
<div class="flex items-center space-x-2">
<p>Listing by</p>
<a routerLink="/details-user/{{ listingUser.id }}" class="text-blue-600 dark:text-blue-500 hover:underline">{{ listingUser.firstname }} {{ listingUser.lastname }}</a>
@if(listingUser.hasCompanyLogo){
<img src="{{ env.imageBaseUrl }}/pictures/logo/{{ listing.imagePath }}.avif?_ts={{ ts }}" class="mr-5 lg:mb-0" style="max-height: 30px; max-width: 100px" />
}
</div>
}
<button (click)="mail()" class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">Submit</button> <button (click)="mail()" class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">Submit</button>
</div> </div>
</form> </form>

View File

@ -111,6 +111,16 @@ export class DetailsCommercialPropertyListingComponent extends BaseDetailsCompon
{ label: this.listing.location.name ? 'City' : 'County', value: this.listing.location.name ? this.listing.location.name : this.listing.location.county }, { label: this.listing.location.name ? 'City' : 'County', value: this.listing.location.name ? this.listing.location.name : this.listing.location.county },
{ label: 'Asking Price:', value: `$${this.listing.price?.toLocaleString()}` }, { label: 'Asking Price:', value: `$${this.listing.price?.toLocaleString()}` },
{ label: 'Listed since', value: `${this.dateInserted()} - ${this.getDaysListed()} days` }, { label: 'Listed since', value: `${this.dateInserted()} - ${this.getDaysListed()} days` },
{
label: 'Listing by',
value: null, // Wird nicht verwendet
isHtml: true,
isListingBy: true, // Flag für den speziellen Fall
user: this.listingUser, // Übergebe das User-Objekt
imagePath: this.listing.imagePath,
imageBaseUrl: this.env.imageBaseUrl,
ts: this.ts,
},
]; ];
if (this.listing.draft) { if (this.listing.draft) {
this.propertyDetails.push({ label: 'Draft', value: this.listing.draft ? 'Yes' : 'No' }); this.propertyDetails.push({ label: 'Draft', value: this.listing.draft ? 'Yes' : 'No' });

View File

@ -15,7 +15,7 @@ import { ListingsService } from '../../../services/listings.service';
import { SearchService } from '../../../services/search.service'; import { SearchService } from '../../../services/search.service';
import { SelectOptionsService } from '../../../services/select-options.service'; import { SelectOptionsService } from '../../../services/select-options.service';
import { UserService } from '../../../services/user.service'; import { UserService } from '../../../services/user.service';
import { getCriteriaProxy, resetUserListingCriteria } from '../../../utils/utils'; import { assignProperties, getCriteriaProxy, resetUserListingCriteria } from '../../../utils/utils';
@UntilDestroy() @UntilDestroy()
@Component({ @Component({
selector: 'app-broker-listings', selector: 'app-broker-listings',
@ -104,8 +104,13 @@ export class BrokerListingsComponent {
this.searchService.search(this.criteria); this.searchService.search(this.criteria);
} }
openFilterModal() { async openFilterModal() {
// Open the search modal with current criteria // Open the search modal with current criteria
this.modalService.showModal(this.criteria); const modalResult = await this.modalService.showModal(this.criteria);
if (modalResult.accepted) {
this.searchService.search(this.criteria);
} else {
this.criteria = assignProperties(this.criteria, modalResult.criteria);
}
} }
} }

View File

@ -14,7 +14,7 @@ import { ImageService } from '../../../services/image.service';
import { ListingsService } from '../../../services/listings.service'; import { ListingsService } from '../../../services/listings.service';
import { SearchService } from '../../../services/search.service'; import { SearchService } from '../../../services/search.service';
import { SelectOptionsService } from '../../../services/select-options.service'; import { SelectOptionsService } from '../../../services/select-options.service';
import { getCriteriaProxy, resetBusinessListingCriteria } from '../../../utils/utils'; import { assignProperties, getCriteriaProxy, resetBusinessListingCriteria } from '../../../utils/utils';
@UntilDestroy() @UntilDestroy()
@Component({ @Component({
selector: 'app-business-listings', selector: 'app-business-listings',
@ -107,8 +107,13 @@ export class BusinessListingsComponent {
this.searchService.search(this.criteria); this.searchService.search(this.criteria);
} }
openFilterModal() { async openFilterModal() {
// Open the search modal with current criteria // Open the search modal with current criteria
this.modalService.showModal(this.criteria); const modalResult = await this.modalService.showModal(this.criteria);
if (modalResult.accepted) {
this.searchService.search(this.criteria);
} else {
this.criteria = assignProperties(this.criteria, modalResult.criteria);
}
} }
} }

View File

@ -14,7 +14,7 @@ import { ImageService } from '../../../services/image.service';
import { ListingsService } from '../../../services/listings.service'; import { ListingsService } from '../../../services/listings.service';
import { SearchService } from '../../../services/search.service'; import { SearchService } from '../../../services/search.service';
import { SelectOptionsService } from '../../../services/select-options.service'; import { SelectOptionsService } from '../../../services/select-options.service';
import { getCriteriaProxy, resetCommercialPropertyListingCriteria } from '../../../utils/utils'; import { assignProperties, getCriteriaProxy, resetCommercialPropertyListingCriteria } from '../../../utils/utils';
@UntilDestroy() @UntilDestroy()
@Component({ @Component({
selector: 'app-commercial-property-listings', selector: 'app-commercial-property-listings',
@ -105,8 +105,13 @@ export class CommercialPropertyListingsComponent {
this.searchService.search(this.criteria); this.searchService.search(this.criteria);
} }
openFilterModal() { async openFilterModal() {
// Open the search modal with current criteria // Open the search modal with current criteria
this.modalService.showModal(this.criteria); const modalResult = await this.modalService.showModal(this.criteria);
if (modalResult.accepted) {
this.searchService.search(this.criteria);
} else {
this.criteria = assignProperties(this.criteria, modalResult.criteria);
}
} }
} }

View File

@ -150,7 +150,7 @@ export class EditCommercialPropertyListingComponent {
const email = keycloakUser.email; const email = keycloakUser.email;
this.user = await this.userService.getByMail(email); this.user = await this.userService.getByMail(email);
this.listingCategories = this.selectOptions.listingCategories this.listingCategories = this.selectOptions.listingCategories
.filter(lc => lc.value === 'commercialProperty' || (this.user.customerSubType === 'broker' && lc.value === 'business')) .filter(lc => lc.value === 'commercialProperty' || this.user.customerType === 'professional')
.map(e => { .map(e => {
return { name: e.name, value: e.value }; return { name: e.name, value: e.value };
}); });

View File

@ -11,6 +11,7 @@
<th class="py-2 px-4 text-left">Category</th> <th class="py-2 px-4 text-left">Category</th>
<th class="py-2 px-4 text-left">Located in</th> <th class="py-2 px-4 text-left">Located in</th>
<th class="py-2 px-4 text-left">Price</th> <th class="py-2 px-4 text-left">Price</th>
<th class="py-2 px-4 text-left">Publication Status</th>
<th class="py-2 px-4 text-left">Actions</th> <th class="py-2 px-4 text-left">Actions</th>
</tr> </tr>
</thead> </thead>
@ -20,6 +21,11 @@
<td class="py-2 px-4">{{ listing.listingsCategory === 'commercialProperty' ? 'Commercial Property' : 'Business' }}</td> <td class="py-2 px-4">{{ listing.listingsCategory === 'commercialProperty' ? 'Commercial Property' : 'Business' }}</td>
<td class="py-2 px-4">{{ listing.location.name ? listing.location.name : listing.location.county }}, {{ listing.location.state }}</td> <td class="py-2 px-4">{{ listing.location.name ? listing.location.name : listing.location.county }}, {{ listing.location.state }}</td>
<td class="py-2 px-4">${{ listing.price.toLocaleString() }}</td> <td class="py-2 px-4">${{ listing.price.toLocaleString() }}</td>
<td class="py-2 px-4">
<span class="{{ listing.draft ? 'bg-yellow-100 text-yellow-800' : 'bg-green-100 text-green-800' }} py-1 px-2 rounded-full text-xs font-medium">
{{ listing.draft ? 'Draft' : 'Published' }}
</span>
</td>
<td class="py-2 px-4"> <td class="py-2 px-4">
@if(listing.listingsCategory==='business'){ @if(listing.listingsCategory==='business'){
<button class="bg-green-500 text-white p-2 rounded-full mr-2" [routerLink]="['/editBusinessListing', listing.id]"> <button class="bg-green-500 text-white p-2 rounded-full mr-2" [routerLink]="['/editBusinessListing', listing.id]">
@ -56,6 +62,12 @@
<p class="text-gray-600 mb-2">Category: {{ listing.listingsCategory === 'commercialProperty' ? 'Commercial Property' : 'Business' }}</p> <p class="text-gray-600 mb-2">Category: {{ listing.listingsCategory === 'commercialProperty' ? 'Commercial Property' : 'Business' }}</p>
<p class="text-gray-600 mb-2">Located in: {{ listing.location.name ? listing.location.name : listing.location.county }} - {{ listing.location.state }}</p> <p class="text-gray-600 mb-2">Located in: {{ listing.location.name ? listing.location.name : listing.location.county }} - {{ listing.location.state }}</p>
<p class="text-gray-600 mb-2">Price: ${{ listing.price.toLocaleString() }}</p> <p class="text-gray-600 mb-2">Price: ${{ listing.price.toLocaleString() }}</p>
<div class="flex items-center gap-2 mb-2">
<span class="text-gray-600">Publication Status:</span>
<span class="{{ listing.draft ? 'bg-yellow-100 text-yellow-800' : 'bg-green-100 text-green-800' }} py-1 px-2 rounded-full text-xs font-medium">
{{ listing.draft ? 'Draft' : 'Published' }}
</span>
</div>
<div class="flex justify-start"> <div class="flex justify-start">
@if(listing.listingsCategory==='business'){ @if(listing.listingsCategory==='business'){
<button class="bg-green-500 text-white p-2 rounded-full mr-2" [routerLink]="['/editBusinessListing', listing.id]"> <button class="bg-green-500 text-white p-2 rounded-full mr-2" [routerLink]="['/editBusinessListing', listing.id]">