Favorites #19, Social Media Start #53

This commit is contained in:
2024-08-29 17:13:24 +02:00
parent ede8b66d83
commit 630c31cfc9
19 changed files with 346 additions and 298 deletions

View File

@@ -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">&lt;&lt;</button>
<button class="px-2 py-1 border-t border-b bg-gray-100">&lt;</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">&gt;</button>
<button class="px-2 py-1 border rounded-r-md bg-gray-100">&gt;&gt;</button>
<select class="ml-2 border rounded-md px-2 py-1">
<option>10</option>
</select>
</div>
</div> -->
</div>
</div>
<app-confirmation></app-confirmation>

View File

@@ -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]];
// }
}

View File

@@ -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">&lt;&lt;</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> -->