@@ -2,7 +2,7 @@
|
||||
<div class="bg-white rounded-lg shadow-lg overflow-hidden relative">
|
||||
<button
|
||||
(click)="historyService.goBack()"
|
||||
class="absolute top-4 right-4 bg-red-500 text-white rounded-full w-8 h-8 flex items-center justify-center hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-opacity-50"
|
||||
class="absolute top-4 right-4 bg-red-500 text-white rounded-full w-8 h-8 flex items-center justify-center hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-opacity-50 print:hidden"
|
||||
>
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
@@ -23,78 +23,64 @@
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@if(listing && listingUser && (listingUser?.email===user?.email || isAdmin())){
|
||||
<div class="py-4 print:hidden">
|
||||
@if(listing && listingUser && (listingUser?.email===user?.email || isAdmin())){
|
||||
<div class="inline">
|
||||
<button class="share share-edit text-white font-bold text-xs py-1.5 px-2 inline-flex items-center" [routerLink]="['/editBusinessListing', listing.id]">
|
||||
<i class="fa-solid fa-floppy-disk"></i>
|
||||
<span class="ml-2">Edit</span>
|
||||
</button>
|
||||
</div>
|
||||
} @if(user){
|
||||
<div class="inline">
|
||||
<button class="share share-save text-white font-bold text-xs py-1.5 px-2 inline-flex items-center" (click)="save()" [disabled]="listing.favoritesForUser.includes(user.email)">
|
||||
<i class="fa-solid fa-floppy-disk"></i>
|
||||
@if(listing.favoritesForUser.includes(user.email)){
|
||||
<span class="ml-2">Saved ...</span>
|
||||
}@else {
|
||||
<span class="ml-2">Save</span>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
<share-button button="print" showText="true"></share-button>
|
||||
<!-- <share-button button="email" showText="true"></share-button> -->
|
||||
<div class="inline">
|
||||
<button class="share share-email text-white font-bold text-xs py-1.5 px-2 inline-flex items-center">
|
||||
<i class="fa-solid fa-envelope"></i>
|
||||
<span class="ml-2">Email</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<share-button button="facebook" showText="true"></share-button>
|
||||
<share-button button="x" showText="true"></share-button>
|
||||
<share-button button="linkedin" showText="true"></share-button>
|
||||
</div>
|
||||
<!-- @if(listing && listingUser && (listingUser?.email===user?.email || isAdmin())){
|
||||
<button
|
||||
[routerLink]="['/editBusinessListing', listing.id]"
|
||||
class="w-full sm:w-auto px-4 py-2 mt-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"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
}
|
||||
} -->
|
||||
</div>
|
||||
|
||||
<!-- Right column -->
|
||||
<div class="w-full lg:w-1/2 mt-6 lg:mt-0">
|
||||
<div class="w-full lg:w-1/2 mt-6 lg:mt-0 print:hidden">
|
||||
<h3 class="text-lg font-semibold mb-4">Contact the Author of this Listing</h3>
|
||||
<p class="text-sm mb-4">Please include your contact info below</p>
|
||||
<form class="space-y-4">
|
||||
<!-- <div class="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:space-x-4">
|
||||
<div class="w-full sm:w-1/2">
|
||||
<label for="name" class="block text-sm font-medium text-gray-700">Your Name</label>
|
||||
<input type="text" id="name" name="name" [(ngModel)]="mailinfo.sender.name" class="mt-1 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm" />
|
||||
</div>
|
||||
<div class="w-full sm:w-1/2">
|
||||
<label for="email" class="block text-sm font-medium text-gray-700">Your Email</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
[(ngModel)]="mailinfo.sender.email"
|
||||
class="mt-1 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<app-validated-input label="Your Name" name="name" [(ngModel)]="mailinfo.sender.name"></app-validated-input>
|
||||
<app-validated-input label="Your Email" name="email" [(ngModel)]="mailinfo.sender.email" kind="email"></app-validated-input>
|
||||
</div>
|
||||
<!-- <div class="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:space-x-4">
|
||||
<div class="w-full sm:w-1/2">
|
||||
<label for="phone" class="block text-sm font-medium text-gray-700">Phone Number</label>
|
||||
<input
|
||||
type="tel"
|
||||
id="phone"
|
||||
name="phone"
|
||||
[(ngModel)]="mailinfo.sender.phoneNumber"
|
||||
placeholder="(123) 456-7890"
|
||||
class="mt-1 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div class="w-full sm:w-1/2">
|
||||
<label for="country" class="block text-sm font-medium text-gray-700">Country/State</label>
|
||||
<input
|
||||
type="text"
|
||||
id="country"
|
||||
name="country"
|
||||
[(ngModel)]="mailinfo.sender.state"
|
||||
class="mt-1 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<app-validated-input label="Phone Number" name="phoneNumber" [(ngModel)]="mailinfo.sender.phoneNumber" kind="tel"></app-validated-input>
|
||||
<app-validated-input label="Country/State" name="state" [(ngModel)]="mailinfo.sender.state"></app-validated-input>
|
||||
</div>
|
||||
<!-- <div>
|
||||
<label for="comments" class="block text-sm font-medium text-gray-700">Questions/Comments</label>
|
||||
<textarea
|
||||
id="comments"
|
||||
name="comments"
|
||||
rows="4"
|
||||
[(ngModel)]="mailinfo.sender.comments"
|
||||
class="mt-1 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
||||
></textarea>
|
||||
</div> -->
|
||||
|
||||
<div>
|
||||
<app-validated-textarea label="Questions/Comments" name="comments" [(ngModel)]="mailinfo.sender.comments"></app-validated-textarea>
|
||||
</div>
|
||||
@@ -116,123 +102,3 @@
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="surface-ground h-full">
|
||||
<div class="px-6 py-5">
|
||||
<div class="surface-card p-4 shadow-2 border-round">
|
||||
<div class="flex justify-content-between align-items-center align-content-center">
|
||||
<div class="font-medium text-3xl text-900 mb-3">{{ listing?.title }}</div>
|
||||
@if(historyService.canGoBack){
|
||||
<p-button icon="pi pi-times" [rounded]="true" severity="danger" (click)="historyService.goBack()"></p-button>
|
||||
}
|
||||
</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">
|
||||
<li class="flex align-items-center py-3 px-2 flex-wrap">
|
||||
<div class="text-500 w-full md:w-3 font-medium flex">Description</div>
|
||||
<div class="text-900 w-full md:w-9 line-height-3 flex flex-column" [innerHTML]="description"></div>
|
||||
</li>
|
||||
<li class="flex align-items-center py-3 px-2 flex-wrap surface-ground">
|
||||
<div class="text-500 w-full md:w-3 font-medium">Category</div>
|
||||
<div class="text-900 w-full md:w-9">
|
||||
<p-chip [label]="selectOptions.getBusiness(listing.type)"></p-chip>
|
||||
</div>
|
||||
</li>
|
||||
<li class="flex align-items-center py-3 px-2 flex-wrap">
|
||||
<div class="text-500 w-full md:w-3 font-medium">Located in</div>
|
||||
<div class="text-900 w-full md:w-9">{{ listing.city }}, {{ selectOptions.getState(listing.state) }}</div>
|
||||
</li>
|
||||
<li class="flex align-items-center py-3 px-2 flex-wrap surface-ground">
|
||||
<div class="text-500 w-full md:w-3 font-medium">Asking Price</div>
|
||||
<div class="text-900 w-full md:w-9">{{ listing.price | currency }}</div>
|
||||
</li>
|
||||
<li class="flex align-items-center py-3 px-2 flex-wrap">
|
||||
<div class="text-500 w-full md:w-3 font-medium">Sales revenue</div>
|
||||
<div class="text-900 w-full md:w-9">{{ listing.salesRevenue | currency }}</div>
|
||||
</li>
|
||||
<li class="flex align-items-center py-3 px-2 flex-wrap surface-ground">
|
||||
<div class="text-500 w-full md:w-3 font-medium">Cash flow</div>
|
||||
<div class="text-900 w-full md:w-9">{{ listing.cashFlow | currency }}</div>
|
||||
</li>
|
||||
<li class="flex align-items-center py-3 px-2 flex-wrap">
|
||||
<div class="text-500 w-full md:w-3 font-medium">Type of Real Estate</div>
|
||||
<div class="text-900 w-full md:w-9">
|
||||
@if (listing.realEstateIncluded){
|
||||
<p-chip label="Real Estate Included"></p-chip>
|
||||
} @if (listing.leasedLocation){
|
||||
<p-chip label="Leased Location"></p-chip>
|
||||
} @if (listing.franchiseResale){
|
||||
<p-chip label="Franchise Re-Sale"></p-chip>
|
||||
}
|
||||
</div>
|
||||
</li>
|
||||
<li class="flex align-items-center py-3 px-2 flex-wrap surface-ground">
|
||||
<div class="text-500 w-full md:w-3 font-medium">Employees</div>
|
||||
<div class="text-900 w-full md:w-9">{{ listing.employees }}</div>
|
||||
</li>
|
||||
<li class="flex align-items-center py-3 px-2 flex-wrap">
|
||||
<div class="text-500 w-full md:w-3 font-medium">Established since</div>
|
||||
<div class="text-900 w-full md:w-9">{{ listing.established }}</div>
|
||||
</li>
|
||||
<li class="flex align-items-center py-3 px-2 flex-wrap surface-ground">
|
||||
<div class="text-500 w-full md:w-3 font-medium">Support & Training</div>
|
||||
<div class="text-900 w-full md:w-9">{{ listing.supportAndTraining }}</div>
|
||||
</li>
|
||||
<li class="flex align-items-center py-3 px-2 flex-wrap">
|
||||
<div class="text-500 w-full md:w-3 font-medium">Reason for Sale</div>
|
||||
<div class="text-900 w-full md:w-9">{{ listing.reasonForSale }}</div>
|
||||
</li>
|
||||
<li class="flex align-items-center py-3 px-2 flex-wrap surface-ground">
|
||||
<div class="text-500 w-full md:w-3 font-medium">Broker licensing</div>
|
||||
<div class="text-900 w-full md:w-9">{{ listing.brokerLicencing }}</div>
|
||||
</li>
|
||||
</ul>
|
||||
@if(listing && listingUser && (listingUser?.email===user?.email || isAdmin())){
|
||||
<button pButton pRipple label="Edit" icon="pi pi-file-edit" class="w-auto" [routerLink]="['/editBusinessListing', listing.id]"></button>
|
||||
}
|
||||
</div>
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="surface-card p-4 border-round p-fluid">
|
||||
<div class="font-medium text-xl text-primary text-900 mb-3">Contact the Author of this Listing</div>
|
||||
<div class="font-italic text-sm text-900 mb-5">Please include your contact info below</div>
|
||||
<div class="grid formgrid p-fluid">
|
||||
<div class="field mb-4 col-12 md:col-6">
|
||||
<label for="name" class="font-medium text-900">Your Name</label>
|
||||
<input id="name" type="text" pInputText [(ngModel)]="mailinfo.sender.name" />
|
||||
</div>
|
||||
<div class="field mb-4 col-12 md:col-6">
|
||||
<label for="email" class="font-medium text-900">Your Email</label>
|
||||
<input id="email" type="text" pInputText [(ngModel)]="mailinfo.sender.email" />
|
||||
</div>
|
||||
<div class="field mb-4 col-12 md:col-6">
|
||||
<label for="phoneNumber" class="font-medium text-900">Phone Number</label>
|
||||
<p-inputMask mask="(999) 999-9999" placeholder="(123) 456-7890" [(ngModel)]="mailinfo.sender.phoneNumber"></p-inputMask>
|
||||
</div>
|
||||
<div class="field mb-4 col-12 md:col-6">
|
||||
<label for="state" class="font-medium text-900">Country/State</label>
|
||||
<input id="state" type="text" pInputText [(ngModel)]="mailinfo.sender.state" />
|
||||
</div>
|
||||
<div class="surface-border border-top-1 opacity-50 mb-4 col-12"></div>
|
||||
<div class="field mb-4 col-12">
|
||||
<label for="notes" class="font-medium text-900">Questions/Comments</label>
|
||||
<textarea id="notes" pInputTextarea [autoResize]="true" [rows]="5" [(ngModel)]="mailinfo.sender.comments"></textarea>
|
||||
</div>
|
||||
@if(listingUser){
|
||||
<div class="surface-border mb-4 col-12 flex align-items-center">
|
||||
Listing by <a routerLink="/details-user/{{ listingUser.id }}" class="mr-2 font-semibold">{{ listingUser.firstname }} {{ listingUser.lastname }}</a>
|
||||
@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>
|
||||
}
|
||||
</div>
|
||||
<button pButton pRipple label="Submit" icon="pi pi-file" class="w-auto" (click)="mail()"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Component } from '@angular/core';
|
||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { ShareButton } from 'ngx-sharebuttons/button';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||
import { KeycloakUser, MailInfo } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
@@ -21,7 +22,7 @@ import { createMailInfo, map2User } from '../../../utils/utils';
|
||||
@Component({
|
||||
selector: 'app-details-business-listing',
|
||||
standalone: true,
|
||||
imports: [SharedModule, ValidatedInputComponent, ValidatedTextareaComponent],
|
||||
imports: [SharedModule, ValidatedInputComponent, ValidatedTextareaComponent, ShareButton],
|
||||
providers: [],
|
||||
templateUrl: './details-business-listing.component.html',
|
||||
styleUrl: '../details.scss',
|
||||
@@ -145,4 +146,11 @@ export class DetailsBusinessListingComponent {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
save() {
|
||||
this.listing.favoritesForUser.push(this.user.email);
|
||||
this.listingsService.save(this.listing, 'business');
|
||||
}
|
||||
isAlreadyFavorite() {
|
||||
return this.listing.favoritesForUser.includes(this.user.email);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,3 +51,22 @@
|
||||
margin-bottom: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
button.share {
|
||||
font-size: 13px;
|
||||
transform: translateY(-2px) scale(1.03);
|
||||
margin-right: 4px;
|
||||
margin-left: 2px;
|
||||
border-radius: 4px;
|
||||
i {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
.share-edit {
|
||||
background-color: #0088cc;
|
||||
}
|
||||
.share-save {
|
||||
background-color: #e60023;
|
||||
}
|
||||
.share-email {
|
||||
background-color: #ff961c;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,54 @@
|
||||
<div class="container mx-auto p-4">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<!-- Anzahl der Spalten auf 3 reduziert und den Abstand erhöht -->
|
||||
@for (listing of listings; track listing.id) {
|
||||
<div class="bg-white rounded-lg shadow-lg overflow-hidden hover:shadow-xl">
|
||||
<!-- Hover-Effekt hinzugefügt -->
|
||||
<div class="p-6 flex flex-col h-full relative z-[0]">
|
||||
<div class="flex items-center mb-4">
|
||||
<i [class]="selectOptions.getIconAndTextColorType(listing.type)" class="mr-2 text-xl"></i>
|
||||
<!-- Icon vergrößert -->
|
||||
<span [class]="selectOptions.getTextColorType(listing.type)" class="font-bold text-lg">{{ selectOptions.getBusiness(listing.type) }}</span>
|
||||
<!-- Schriftgröße erhöht -->
|
||||
</div>
|
||||
<h2 class="text-xl font-semibold mb-4">
|
||||
<!-- Überschrift vergrößert -->
|
||||
{{ listing.title }}
|
||||
@if(listing.draft){
|
||||
<span class="bg-red-100 text-red-800 text-sm font-medium me-2 ml-2 px-2.5 py-0.5 rounded dark:bg-red-900 dark:text-red-300">Draft</span>
|
||||
}
|
||||
</h2>
|
||||
<!-- State Badge -->
|
||||
<span class="w-fit inline-flex items-center justify-center px-2 py-1 mb-4 text-xs font-bold leading-none bg-gray-200 text-gray-700 rounded-full">
|
||||
{{ selectOptions.getState(listing.location.state) }}
|
||||
</span>
|
||||
|
||||
<!-- Asking Price hervorgehoben -->
|
||||
<p class="text-base font-bold text-gray-800 mb-2">
|
||||
<strong>Asking price:</strong> <span class="text-green-600"> {{ listing.price | currency : 'USD' : 'symbol' : '1.0-0' }}</span>
|
||||
</p>
|
||||
<p class="text-sm text-gray-600 mb-2"><strong>Sales revenue:</strong> {{ listing.salesRevenue | currency : 'USD' : 'symbol' : '1.0-0' }}</p>
|
||||
<p class="text-sm text-gray-600 mb-2"><strong>Net profit:</strong> {{ listing.cashFlow | currency : 'USD' : 'symbol' : '1.0-0' }}</p>
|
||||
<p class="text-sm text-gray-600 mb-2"><strong>Location:</strong> {{ listing.location.name }}</p>
|
||||
<p class="text-sm text-gray-600 mb-4"><strong>Established:</strong> {{ listing.established }}</p>
|
||||
<img src="{{ env.imageBaseUrl }}/pictures/logo/{{ listing.imageName }}.avif?_ts={{ ts }}" alt="Company logo" class="absolute bottom-[80px] right-[20px] h-[45px] w-auto" />
|
||||
<!-- Position und Größe des Bildes angepasst -->
|
||||
<div class="flex-grow"></div>
|
||||
<button
|
||||
class="bg-green-500 text-white px-5 py-3 rounded-full w-full flex items-center justify-center mt-4 transition-colors duration-200 hover:bg-green-600"
|
||||
[routerLink]="['/details-business-listing', listing.id]"
|
||||
>
|
||||
<!-- Button-Größe und Hover-Effekt verbessert -->
|
||||
View Full Listing
|
||||
<i class="fas fa-arrow-right ml-2"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="container mx-auto p-4">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
@for (listing of listings; track listing.id) {
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden">
|
||||
@@ -28,7 +78,7 @@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
@if(pageCount>1){
|
||||
<app-paginator [page]="page" [pageCount]="pageCount" (pageChange)="onPageChange($event)"></app-paginator>
|
||||
}
|
||||
|
||||
@@ -1,30 +1,85 @@
|
||||
<!--
|
||||
<div class="surface-ground px-4 py-8 md:px-6 lg:px-8 h-full">
|
||||
<div class="p-fluid flex flex-column lg:flex-row">
|
||||
<menu-account></menu-account>
|
||||
<div class="surface-card p-5 shadow-2 border-round flex-auto">
|
||||
<div class="text-900 font-semibold text-lg mt-3">My Favorites</div>
|
||||
<p-divider></p-divider>
|
||||
<p-table [value]="favorites" [tableStyle]="{ 'min-width': '50rem' }" dataKey="id" [paginator]="true" [rows]="10" [rowsPerPageOptions]="[10, 20, 50]" [showCurrentPageReport]="true" currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries">
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
<th class="wide-column">Title</th>
|
||||
<th>Category</th>
|
||||
<th>Located in</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="body" let-listing>
|
||||
<tr>
|
||||
<td class="wide-column line-height-3">{{ listing.title }}</td>
|
||||
<td>{{ selectOptions.getListingsCategory(listing.listingsCategory) }}</td>
|
||||
<td>{{ selectOptions.getState(listing.state) }}</td>
|
||||
<td>
|
||||
<button pButton pRipple icon="pi pi-eye" class="p-button-rounded p-button-success mr-2" [routerLink]="['/details',listing.id]"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
</div>
|
||||
<div class="container mx-auto p-4">
|
||||
<div class="bg-white rounded-lg shadow-md p-6">
|
||||
<h1 class="text-2xl font-bold md:mb-4">My Favorites</h1>
|
||||
|
||||
<!-- Desktop view -->
|
||||
<div class="hidden md:block">
|
||||
<table class="w-full bg-white shadow-md rounded-lg overflow-hidden">
|
||||
<thead class="bg-gray-100">
|
||||
<tr>
|
||||
<th class="py-2 px-4 text-left">Title</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">Price</th>
|
||||
<th class="py-2 px-4 text-left">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for(listing of favorites; track listing){
|
||||
<tr class="border-b">
|
||||
<td class="py-2 px-4">{{ listing.title }}</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.state }}</td>
|
||||
<td class="py-2 px-4">${{ listing.price.toLocaleString() }}</td>
|
||||
<td class="py-2 px-4 flex">
|
||||
@if(listing.listingsCategory==='business'){
|
||||
<button class="bg-green-500 text-white w-10 h-10 flex items-center justify-center rounded-full mr-2" [routerLink]="['/details-business-listing', listing.id]">
|
||||
<i class="fa-regular fa-eye"></i>
|
||||
</button>
|
||||
|
||||
} @if(listing.listingsCategory==='commercialProperty'){
|
||||
<button class="bg-green-500 text-white w-10 h-10 flex items-center justify-center rounded-full mr-2" [routerLink]="['/details-business-listing', listing.id]">
|
||||
<i class="fa-regular fa-eye"></i>
|
||||
</button>
|
||||
}
|
||||
<button class="bg-red-500 text-white w-10 h-10 flex items-center justify-center rounded-full mr-2" (click)="confirmDelete(listing)">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- Mobile view -->
|
||||
<div class="md:hidden">
|
||||
<div *ngFor="let listing of favorites" class="bg-white shadow-md rounded-lg p-4 mb-4">
|
||||
<h2 class="text-xl font-semibold mb-2">{{ listing.title }}</h2>
|
||||
<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.state }}</p>
|
||||
<p class="text-gray-600 mb-2">Price: ${{ listing.price.toLocaleString() }}</p>
|
||||
<div class="flex justify-start">
|
||||
@if(listing.listingsCategory==='business'){
|
||||
<button class="bg-green-500 text-white w-10 h-10 flex items-center justify-center rounded-full mr-2" [routerLink]="['/details-business-listing', listing.id]">
|
||||
<i class="fa-regular fa-eye"></i>
|
||||
</button>
|
||||
|
||||
} @if(listing.listingsCategory==='commercialProperty'){
|
||||
<button class="bg-green-500 text-white w-10 h-10 flex items-center justify-center rounded-full mr-2" [routerLink]="['/details-business-listing', listing.id]">
|
||||
<i class="fa-regular fa-eye"></i>
|
||||
</button>
|
||||
}
|
||||
<button class="bg-red-500 text-white w-10 h-10 flex items-center justify-center rounded-full mr-2" (click)="confirmDelete(listing)">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="flex items-center justify-between mt-4">
|
||||
<p class="text-sm text-gray-600">Showing 1 to 2 of 2 entries</p>
|
||||
<div class="flex items-center">
|
||||
<button class="px-2 py-1 border rounded-l-md bg-gray-100"><<</button>
|
||||
<button class="px-2 py-1 border-t border-b bg-gray-100"><</button>
|
||||
<button class="px-2 py-1 border bg-blue-500 text-white">1</button>
|
||||
<button class="px-2 py-1 border-t border-b bg-gray-100">></button>
|
||||
<button class="px-2 py-1 border rounded-r-md bg-gray-100">>></button>
|
||||
<select class="ml-2 border rounded-md px-2 py-1">
|
||||
<option>10</option>
|
||||
</select>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<app-confirmation></app-confirmation>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { KeycloakUser, ListingType } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { BusinessListing, CommercialPropertyListing } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||
import { KeycloakUser } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||
import { ConfirmationComponent } from '../../../components/confirmation/confirmation.component';
|
||||
import { ConfirmationService } from '../../../components/confirmation/confirmation.service';
|
||||
import { ListingsService } from '../../../services/listings.service';
|
||||
import { SelectOptionsService } from '../../../services/select-options.service';
|
||||
import { SharedModule } from '../../../shared/shared/shared.module';
|
||||
@@ -9,18 +12,56 @@ import { map2User } from '../../../utils/utils';
|
||||
@Component({
|
||||
selector: 'app-favorites',
|
||||
standalone: true,
|
||||
imports: [SharedModule],
|
||||
imports: [SharedModule, ConfirmationComponent],
|
||||
templateUrl: './favorites.component.html',
|
||||
styleUrl: './favorites.component.scss',
|
||||
})
|
||||
export class FavoritesComponent {
|
||||
user: KeycloakUser;
|
||||
listings: Array<ListingType> = []; //= dataListings as unknown as Array<BusinessListing>;
|
||||
favorites: Array<ListingType>;
|
||||
constructor(public keycloakService: KeycloakService, private listingsService: ListingsService, public selectOptions: SelectOptionsService) {}
|
||||
// listings: Array<ListingType> = []; //= dataListings as unknown as Array<BusinessListing>;
|
||||
favorites: Array<BusinessListing | CommercialPropertyListing>;
|
||||
constructor(public keycloakService: KeycloakService, private listingsService: ListingsService, public selectOptions: SelectOptionsService, private confirmationService: ConfirmationService) {}
|
||||
async ngOnInit() {
|
||||
const token = await this.keycloakService.getToken();
|
||||
this.user = map2User(token);
|
||||
this.favorites = this.listings.filter(l => l.favoritesForUser?.includes(this.user.id));
|
||||
const result = await Promise.all([await this.listingsService.getFavoriteListings('business'), await this.listingsService.getFavoriteListings('commercialProperty')]);
|
||||
this.favorites = [...result[0], ...result[1]];
|
||||
}
|
||||
async confirmDelete(listing: BusinessListing | CommercialPropertyListing) {
|
||||
const confirmed = await this.confirmationService.showConfirmation({ message: `Are you sure you want to remove this listing from your Favorites?` });
|
||||
if (confirmed) {
|
||||
// this.messageService.showMessage('Listing has been deleted');
|
||||
this.deleteListing(listing);
|
||||
}
|
||||
}
|
||||
async deleteListing(listing: BusinessListing | CommercialPropertyListing) {
|
||||
if (listing.listingsCategory === 'business') {
|
||||
await this.listingsService.removeFavorite(listing.id, 'business');
|
||||
} else {
|
||||
await this.listingsService.removeFavorite(listing.id, 'commercialProperty');
|
||||
}
|
||||
const result = await Promise.all([await this.listingsService.getFavoriteListings('business'), await this.listingsService.getFavoriteListings('commercialProperty')]);
|
||||
this.favorites = [...result[0], ...result[1]];
|
||||
}
|
||||
// listings: Array<ListingType> = []; //dataListings as unknown as Array<BusinessListing>;
|
||||
// myListings: Array<ListingType>;
|
||||
// user: User;
|
||||
// constructor(
|
||||
// public userService: UserService,
|
||||
// public keycloakService: KeycloakService,
|
||||
// private listingsService: ListingsService,
|
||||
// private cdRef: ChangeDetectorRef,
|
||||
// public selectOptions: SelectOptionsService,
|
||||
// private messageService: MessageService,
|
||||
// private confirmationService: ConfirmationService,
|
||||
// ) {}
|
||||
// async ngOnInit() {
|
||||
// // const keycloakUser = this.userService.getKeycloakUser();
|
||||
// const token = await this.keycloakService.getToken();
|
||||
// const keycloakUser = map2User(token);
|
||||
// const email = keycloakUser.email;
|
||||
// this.user = await this.userService.getByMail(email);
|
||||
// const result = await Promise.all([await this.listingsService.getListingsByEmail(this.user.email, 'business'), await this.listingsService.getListingsByEmail(this.user.email, 'commercialProperty')]);
|
||||
// this.myListings = [...result[0], ...result[1]];
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="container mx-auto p-4">
|
||||
<div class="bg-white rounded-lg shadow-md p-6">
|
||||
<h1 class="text-2xl font-bold mb-4">My Listings</h1>
|
||||
<h1 class="text-2xl font-bold md:mb-4">My Listings</h1>
|
||||
|
||||
<!-- Desktop view -->
|
||||
<div class="hidden md:block">
|
||||
@@ -10,6 +10,7 @@
|
||||
<th class="py-2 px-4 text-left">Title</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">Price</th>
|
||||
<th class="py-2 px-4 text-left">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -17,7 +18,8 @@
|
||||
<tr *ngFor="let listing of myListings" class="border-b">
|
||||
<td class="py-2 px-4">{{ listing.title }}</td>
|
||||
<td class="py-2 px-4">{{ listing.listingsCategory === 'commercialProperty' ? 'Commercial Property' : 'Business' }}</td>
|
||||
<td class="py-2 px-4">{{ listing.location.state }}</td>
|
||||
<td class="py-2 px-4">{{ listing.location.name }}, {{ listing.location.state }}</td>
|
||||
<td class="py-2 px-4">${{ listing.price.toLocaleString() }}</td>
|
||||
<td class="py-2 px-4">
|
||||
@if(listing.listingsCategory==='business'){
|
||||
<button class="bg-green-500 text-white p-2 rounded-full mr-2" [routerLink]="['/editBusinessListing', listing.id]">
|
||||
@@ -52,8 +54,9 @@
|
||||
<div *ngFor="let listing of myListings" class="bg-white shadow-md rounded-lg p-4 mb-4">
|
||||
<h2 class="text-xl font-semibold mb-2">{{ listing.title }}</h2>
|
||||
<p class="text-gray-600 mb-2">Category: {{ listing.listingsCategory === 'commercialProperty' ? 'Commercial Property' : 'Business' }}</p>
|
||||
<p class="text-gray-600 mb-4">Located in: {{ listing.location.name }} - {{ listing.location.state }}</p>
|
||||
<div class="flex justify-end">
|
||||
<p class="text-gray-600 mb-2">Located in: {{ listing.location.name }} - {{ listing.location.state }}</p>
|
||||
<p class="text-gray-600 mb-2">Price: ${{ listing.price.toLocaleString() }}</p>
|
||||
<div class="flex justify-start">
|
||||
<button class="bg-green-500 text-white p-2 rounded-full mr-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
|
||||
@@ -72,7 +75,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between mt-4">
|
||||
<!-- <div class="flex items-center justify-between mt-4">
|
||||
<p class="text-sm text-gray-600">Showing 1 to 2 of 2 entries</p>
|
||||
<div class="flex items-center">
|
||||
<button class="px-2 py-1 border rounded-l-md bg-gray-100"><<</button>
|
||||
@@ -84,52 +87,7 @@
|
||||
<option>10</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<app-confirmation></app-confirmation>
|
||||
<!-- <div class="surface-ground px-4 py-8 md:px-6 lg:px-8 h-full">
|
||||
<div class="p-fluid flex flex-column lg:flex-row">
|
||||
<menu-account></menu-account>
|
||||
<p-toast></p-toast>
|
||||
<p-confirmPopup></p-confirmPopup>
|
||||
<div class="surface-card p-5 shadow-2 border-round flex-auto">
|
||||
<div class="text-900 font-semibold text-lg mt-3">My Listings</div>
|
||||
<p-divider></p-divider>
|
||||
<p-table
|
||||
[value]="myListings"
|
||||
[tableStyle]="{ 'min-width': '50rem' }"
|
||||
dataKey="id"
|
||||
[paginator]="true"
|
||||
[rows]="10"
|
||||
[rowsPerPageOptions]="[10, 20, 50]"
|
||||
[showCurrentPageReport]="true"
|
||||
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"
|
||||
>
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
<th class="wide-column">Title</th>
|
||||
<th>Category</th>
|
||||
<th>Located in</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="body" let-listing>
|
||||
<tr>
|
||||
<td class="wide-column line-height-3">{{ listing.title }}</td>
|
||||
<td>{{ selectOptions.getListingsCategory(listing.listingsCategory) }}</td>
|
||||
<td>{{ selectOptions.getState(listing.state) }}</td>
|
||||
<td>
|
||||
@if(listing.listingsCategory==='business'){
|
||||
<button pButton pRipple icon="pi pi-pencil" class="p-button-rounded p-button-success mr-2" [routerLink]="['/editBusinessListing', listing.id]"></button>
|
||||
} @if(listing.listingsCategory==='commercialProperty'){
|
||||
<button pButton pRipple icon="pi pi-pencil" class="p-button-rounded p-button-success mr-2" [routerLink]="['/editCommercialPropertyListing', listing.id]"></button>
|
||||
}
|
||||
<button pButton pRipple icon="pi pi-trash" class="p-button-rounded p-button-warning" (click)="confirm($event, listing)"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
Reference in New Issue
Block a user