Skip to content

Commit

Permalink
Merge branch '12-Advertisment' of https://github.com/UdL-EPS-SoftArch…
Browse files Browse the repository at this point in the history
…/myapartments into 12-Advertisment
  • Loading branch information
AdriaCreus committed Dec 12, 2024
2 parents 6ce57c9 + 5bbf375 commit 2dfd156
Show file tree
Hide file tree
Showing 24 changed files with 762 additions and 29 deletions.
6 changes: 3 additions & 3 deletions src/app/advertisement/advertisement.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { HateoasResourceOperation, ResourceCollection } from '@lagoshny/ngx-hateoas-client';
import { HateoasResourceOperation, PagedResourceCollection, ResourceCollection } from '@lagoshny/ngx-hateoas-client';
import { Advertisement } from './advertisement';

@Injectable({
Expand All @@ -16,8 +16,8 @@ export class AdvertisementService extends HateoasResourceOperation<Advertisement
return this.searchCollection('findByTitle', { params: { text: query } });
}

public getAllAdvertisements(): Observable<ResourceCollection<Advertisement>> {
return this.getCollection();
public getAllAdvertisements(): Observable<PagedResourceCollection<Advertisement>> {
return this.getPage();
}

public getAdvertisementById(advertisementId: number): Observable<Advertisement> {
Expand Down
2 changes: 1 addition & 1 deletion src/app/advertisement/advertisement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { HateoasResource, Resource } from "@lagoshny/ngx-hateoas-client";
import { Apartment } from "../apartment/apartment";
import { AdvertisementStatus } from "../advertisement-status/advertisementStatus";

@HateoasResource('advertisement')
@HateoasResource('advertisements')
export class Advertisement extends Resource {
id: number = 0;
title: string = '';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,41 @@
<div class="row">
<div class="col-12">
<div class="card" *ngFor="let advertisement of advertisements">
<div class="card" *ngFor="let ad of advertisements">
<div class="card-block">
<div class="card-header row m-1 text-center">
<h5>Advertisement</h5>
</div>
<div class="card-body row m-1">
<div class="col-md-6 p-3">
<h6 class="card-subtitle text-muted">Title</h6>
<p class="card-text">{{ advertisement.title }}</p>
<p class="card-text">{{ ad.title }}</p>
</div>
<div class="col-md-6 p-3">
<h6 class="card-subtitle text-muted">Price</h6>
<p class="card-text">{{ advertisement.price | currency }}</p>
<p class="card-text">{{ ad.price | currency }}</p>
</div>
<div class="col-md-6 p-3">
<h6 class="card-subtitle text-muted">Zip Code</h6>
<p class="card-text">{{ advertisement.zipCode }}</p>
<p class="card-text">{{ ad.zipCode }}</p>
</div>
<div class="col-md-6 p-3">
<h6 class="card-subtitle text-muted">Country</h6>
<p class="card-text">{{ advertisement.country }}</p>
<p class="card-text">{{ ad.country }}</p>
</div>
<div class="col-md-6 p-3">
<h6 class="card-subtitle text-muted">Address</h6>
<p class="card-text">{{ advertisement.address }}</p>
<p class="card-text">{{ ad.address }}</p>
</div>
<div class="col-md-6 p-3">
<h6 class="card-subtitle text-muted">Creation Date</h6>
<p class="card-text">{{ advertisement.creationDate | date: 'dd/MM/yyyy HH:mm:ss' }}</p>
<p class="card-text">{{ ad.creationDate | date: 'dd/MM/yyyy HH:mm:ss' }}</p>
</div>
<div class="col-lg-12 col-md-12 p-3">
<div class="col-12 p-3">
<h6 class="card-subtitle text-muted">Description</h6>
<p class="card-text">{{ advertisement.description }}</p>
<p class="card-text">{{ ad.description }}</p>
</div>
</div>
</div>
</div>
</div>
</div>

<div class="row">
<hr class="my-3">
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,6 @@ <h1 class="mb-4">Create Apartment</h1>
<div class="mb-3">
<a href="/room/create"><button type="button" class="btn btn-secondary">Add Room</button></a>
</div>
<div class="mb-3">
<label for="detail" class="form-label">Apartment Details</label>
<input type="text" class="form-control" id="detail" required [(ngModel)]="apartment.detail" name="detail">
</div>

<button type="submit" class="btn btn-primary mt-3">Submit</button>
</form>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { FormsModule } from '@angular/forms';
import { ErrorMessageService } from '../../error-handler/error-message.service';
import { CommonModule } from '@angular/common';
import { ApartmentService } from '../apartment.service';
import { ApartmentDetails } from '../apartment-details';

@Component({
selector: 'app-apartment-create',
Expand Down Expand Up @@ -40,6 +41,7 @@ export class ApartmentCreateComponent implements OnInit {

this.apartment.owner = this.user;
this.apartment.registrationDate = new Date();
this.apartment.apartmentDetails = new ApartmentDetails();

this.apartmentService.createResource({ body: this.apartment }).subscribe(() => {
this.router.navigate(['/apartment' + this.apartment.id]);
Expand Down Expand Up @@ -78,6 +80,4 @@ export class ApartmentCreateComponent implements OnInit {
URL.revokeObjectURL(this.selectedImages[index].url);
this.selectedImages.splice(index, 1);
}


}
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ApartmentDeleteComponent } from './apartment-delete.component';

describe('ApartmentDeleteComponent', () => {
let component: ApartmentDeleteComponent;
let fixture: ComponentFixture<ApartmentDeleteComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ApartmentDeleteComponent]
})
.compileComponents();

fixture = TestBed.createComponent(ApartmentDeleteComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
83 changes: 83 additions & 0 deletions src/app/apartment/apartment-delete/apartment-delete.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import { ApartmentService } from '../apartment.service';
import { ErrorMessageService } from '../../error-handler/error-message.service';
import {User} from '../../login-basic/user';
import { AuthenticationBasicService } from '../../login-basic/authentication-basic.service';

@Component({
selector: 'app-apartment-delete',
standalone: true,
imports: [],
templateUrl: './apartment-delete.component.html',
styleUrl: './apartment-delete.component.css'
})
export class ApartmentDeleteComponent implements OnInit {
//public apartmentId: string;
public apartmentId: string = '';
public user: User | null = null;
public isAuthorized: boolean = false;

constructor(
private route: ActivatedRoute,
private router: Router,
private apartmentService: ApartmentService,
private errorMessageService: ErrorMessageService,
private authenticationService: AuthenticationBasicService,
) {}

ngOnInit(): void {
this.apartmentId = this.route.snapshot.paramMap.get('id') || '';
// Intentem obtenir l'usuari actual
try {
this.user = this.authenticationService.getCurrentUser();

if (!this.user) {
throw new Error('No user found');
}

// Verifiquem si està autoritzat
this.isAuthorized = this.isAuthorised();

if (this.isAuthorized) {
this.removeApartment();
} else {
this.onUnauthorised();
}
} catch (error) {
console.error('Error during user authentication:', error);
this.errorMessageService.showErrorMessage('Authentication error. Please log in again.');
this.router.navigate(['/login']);
}
}

private removeApartment(): void {
this.apartmentService.getResource(this.apartmentId).subscribe(
(apartment) => {
this.apartmentService.deleteResource(apartment).subscribe(
() => {
this.router.navigate(['/apartments']);
},
() => {
this.errorMessageService.showErrorMessage('Failed to delete apartment. Please try again.');
}
);
},
() => {
this.errorMessageService.showErrorMessage('Failed to load apartment for deletion.');
}
);
}

private isAuthorised(): boolean {
if (!this.user) {
return false;
}
return this.user && (this.user.getRoles().includes('admin') || this.user.getRoles().includes('owner'));
}

onUnauthorised(): void {
this.errorMessageService.showErrorMessage('You are not authorized to create an apartment');
this.router.navigate(['/apartments']);
}
}
24 changes: 24 additions & 0 deletions src/app/apartment/apartment-details.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { HateoasResource, Resource } from '@lagoshny/ngx-hateoas-client';

@HateoasResource('apartments')
export class ApartmentDetails extends Resource {
id: number = 0;
square: number = 0;
numBathrooms: number = 0;
numBedrooms: number = 0;
hasAc: boolean = false;
hasElevator: boolean = false;

constructor(values: object = {}) {
super();
Object.assign(this, values);
}

getIdFromLinks(): string {
if (this._links?.self?.href) {
return this._links.self.href.split('/').pop() || '';
}
return this.id.toString();
}

}
35 changes: 35 additions & 0 deletions src/app/apartment/apartment-update/apartment-update.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.container {
background-color: #f8f9fa;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

h1 {
font-size: 2rem;
font-weight: 600;
color: #343a40;
}

.form-label {
font-weight: 500;
color: #495057;
}

.form-control {
border-radius: 0.25rem;
}

.btn-primary {
background-color: #007bff;
border-color: #007bff;
}

.btn-secondary {
background-color: #6c757d;
border-color: #6c757d;
}

.alert {
font-size: 1rem;
font-weight: 500;
}
98 changes: 98 additions & 0 deletions src/app/apartment/apartment-update/apartment-update.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<div *ngIf="isAuthorized" class="container mt-5 w-50 p-3">

@if (isLoading) {
<div class="d-flex justify-content-center align-items-center">
<div class="spinner-border" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
}
@else if (errorFetchMsg){
<div class="alert alert-danger" role="alert">
{{ errorFetchMsg }}
</div>
}
@else {
<h1 class="mb-4">Update Apartment</h1>


<div class="mb-3">
<label for="images" class="form-label">Images</label>
<input type="file" class="form-control" id="images" (change)="onFileChange($event)" multiple>
<div class="mt-3 d-flex flex-wrap">
<div *ngFor="let image of selectedImages; let i = index" class="me-3 mb-3" style="position: relative; width: 100px; height: 100px; overflow: hidden; border: 1px solid #ccc; border-radius: 8px;">
<img [src]="image.url" alt="Selected image" style="width: 100%; height: 100%; object-fit: cover;">
<button type="button" (click)="removeImage(i)" style="position: absolute; top: 5px; right: 5px; background: dodgerblue; color: white; border: none; border-radius: 50%; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; font-size: 16px; cursor: pointer;">
×
</button>
</div>
</div>

</div>

<form (ngSubmit)="onSubmit()" [formGroup]="apartmentForm">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" formControlName="name" class="form-control" id="name" required [(ngModel)]="apartment.name" name="name">
</div>

<div class="mb-3">
<label for="floor" class="form-label">Floor</label>
<input type="number" formControlName="floor" class="form-control" id="floor" required [(ngModel)]="apartment.floor" name="floor">
</div>

<div class="mb-3">
<label for="address" class="form-label">Address</label>
<input type="text" formControlName="address" class="form-control" id="address" required [(ngModel)]="apartment.address" name="address">

</div>

<div class="mb-3">
<label for="postalCode" class="form-label">Postal Code</label>
<input type="text" formControlName="postalCode" class="form-control" id="postalCode" required [(ngModel)]="apartment.postalCode" name="postalCode">
</div>

<div class="mb-3">
<label for="city" class="form-label">City</label>
<input type="text" formControlName="city" class="form-control" id="city" required [(ngModel)]="apartment.city" name="city">
</div>

<div class="mb-3">
<label for="country" class="form-label">Country</label>
<input type="text" formControlName="country" class="form-control" id="country" required [(ngModel)]="apartment.country" name="country">
</div>

<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" formControlName="description" id="description" rows="3" required [(ngModel)]="apartment.description" name="description" style="resize: vertical; min-height: 100px; max-height: 300px;"></textarea>
</div>

<div class="mb-3">
<a href="/room/create"><button type="button" class="btn btn-secondary">Add Room</button></a>
</div>

<div class="mb-3">
<label for="detail" class="form-label">Apartment Details</label>
<input type="text" class="form-control" id="detail" required [(ngModel)]="apartment.detail" name="detail">
</div>

<button type="submit" class="btn btn-primary mt-3">Submit</button>
<button type="button" (click) = onCancel() class="btn btn-danger mt-3 fa-pull-right">Cancel</button>
</form>



<div *ngIf="!isAuthorized" class="container mt-5 w-50 p-3">
<div class="alert alert-danger" role="alert">
You are not authorized to create an apartment.
</div>
</div>

}
</div>






Loading

0 comments on commit 2dfd156

Please sign in to comment.