Skip to content

Commit

Permalink
Merge pull request #39 from UdL-EPS-SoftArch/12-Advertisment
Browse files Browse the repository at this point in the history
12 advertisement
  • Loading branch information
rogargon authored Dec 13, 2024
2 parents f0addcf + ebbe1ab commit bebd8a8
Show file tree
Hide file tree
Showing 17 changed files with 376 additions and 2 deletions.
12 changes: 12 additions & 0 deletions src/app/advertisement-status/advertisementStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

import { HateoasResource, Resource } from "@lagoshny/ngx-hateoas-client";

@HateoasResource('advertisement-status')
export class AdvertisementStatus extends Resource {
id: number = 0;
name: string = '';
constructor(values: object = {}) {
super();
Object.assign(this , values);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div>
<h2>Delete Advertisement</h2>
<p>Are you sure you want to delete this advertisement?</p>
<button (click)="deleteAdvertisement()">Delete</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DeleteAdvertisementComponent } from './advertisement-delete.component';
import { AdvertisementService } from '../advertisement.service';
import { of, throwError } from 'rxjs';


class AdvertisementServiceMock {
deleteAdvertisement() {
return of(void 0);
}
}

describe('DeleteAdvertisementComponent', () => {
let component: DeleteAdvertisementComponent;
let fixture: ComponentFixture<DeleteAdvertisementComponent>;
let advertisementService: AdvertisementServiceMock;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [DeleteAdvertisementComponent],
providers: [
{ provide: AdvertisementService, useClass: AdvertisementServiceMock }
]
}).compileComponents();

fixture = TestBed.createComponent(DeleteAdvertisementComponent);
component = fixture.componentInstance;
advertisementService = TestBed.inject(AdvertisementService) as unknown as AdvertisementServiceMock;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});

it('should call deleteAdvertisement on confirmation', () => {
spyOn(window, 'confirm').and.returnValue(true);
spyOn(advertisementService, 'deleteAdvertisement').and.callThrough();

const advertisementId = 1;
component.advertisementId = advertisementId;

component.deleteAdvertisement();

expect(advertisementService.deleteAdvertisement).toHaveBeenCalled();

});

it('should not call deleteAdvertisement if user cancels', () => {
spyOn(window, 'confirm').and.returnValue(false);

const advertisementId = 1;
component.advertisementId = advertisementId;

component.deleteAdvertisement();

expect(advertisementService.deleteAdvertisement).not.toHaveBeenCalled();
});

it('should handle errors correctly', () => {
spyOn(window, 'confirm').and.returnValue(true);

spyOn(advertisementService, 'deleteAdvertisement').and.returnValue(throwError(() => new Error('Deletion failed')));

const advertisementId = 1;
component.advertisementId = advertisementId;

component.deleteAdvertisement();

});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AdvertisementService } from '../advertisement.service';

@Component({
selector: 'app-advertisement-delete',
templateUrl: './advertisement-delete.component.html',
styleUrls: [],
})
export class DeleteAdvertisementComponent implements OnInit {
advertisementId!: number;

constructor(
private route: ActivatedRoute,
private advertisementService: AdvertisementService
) {}

ngOnInit(): void {
this.advertisementId = +this.route.snapshot.paramMap.get('id')!;
console.log('Advertisement ID:', this.advertisementId);
}


deleteAdvertisement(): void {
if (confirm('Are you sure you want to delete this advertisement?')) {
console.log('Attempting to delete advertisement with ID:', this.advertisementId);
this.advertisementService.deleteAdvertisement(this.advertisementId).subscribe({
next: () => {
console.log('Advertisement deleted successfully.');
alert('Advertisement deleted successfully.');
},
error: (err) => {
console.error('Failed to delete advertisement:', err);
alert('Failed to delete the advertisement. Please try again.');
},
});
} else {
console.log('Deletion cancelled.');
}
}

}
Empty file.
48 changes: 48 additions & 0 deletions src/app/advertisement/advertisement.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { HateoasResourceOperation, PagedResourceCollection, ResourceCollection } from '@lagoshny/ngx-hateoas-client';
import { Advertisement } from './advertisement';

@Injectable({
providedIn: 'root'
})
export class AdvertisementService extends HateoasResourceOperation<Advertisement> {
constructor(private http: HttpClient) {
super(Advertisement);
}

public findByTitle(query: string): Observable<ResourceCollection<Advertisement>> {
return this.searchCollection('findByTitle', { params: { text: query } });
}

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

public getAdvertisementById(advertisementId: number): Observable<Advertisement> {
return this.getResource(advertisementId);
}

public getAdvertisementByUrl(advertisementUrl: string): Observable<Advertisement> {
return this.http.get<Advertisement>(advertisementUrl);
}

public deleteAdvertisement(advertisementId: number): Observable<Advertisement> {
const advertisement = new Advertisement();
advertisement.id = advertisementId;
const deleteUrl = `http://localhost:8080/advertisements/${advertisementId}`;
console.log('Deleting advertisement from URL: ', deleteUrl);
advertisement.uri = deleteUrl;
advertisement['_links'] = {
self: { href: advertisement.uri }
};

return this.deleteResource(advertisement);
}





}
25 changes: 25 additions & 0 deletions src/app/advertisement/advertisement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { HateoasResource, Resource } from "@lagoshny/ngx-hateoas-client";
import { Apartment } from "../apartment/apartment";
import { AdvertisementStatus } from "../advertisement-status/advertisementStatus";

@HateoasResource('advertisements')
export class Advertisement extends Resource {
id: number = 0;
title: string = '';
description: string = '';
price: number = 0.01;
zipCode: string = '';
country: string = '';
address: string = '';
creationDate: Date = new Date();
expirationDate?: Date;
uri?: string;

adStatus: AdvertisementStatus | number = 0;
apartment: Apartment | number = 0;

constructor(values: object = {}) {
super();
Object.assign(this , values);
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<div class="row">
<div class="col-12">
<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">{{ ad.title }}</p>
</div>
<div class="col-md-6 p-3">
<h6 class="card-subtitle text-muted">Price</h6>
<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">{{ ad.zipCode }}</p>
</div>
<div class="col-md-6 p-3">
<h6 class="card-subtitle text-muted">Country</h6>
<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">{{ ad.address }}</p>
</div>
<div class="col-md-6 p-3">
<h6 class="card-subtitle text-muted">Creation Date</h6>
<p class="card-text">{{ ad.creationDate | date: 'dd/MM/yyyy HH:mm:ss' }}</p>
</div>
<div class="col-12 p-3">
<h6 class="card-subtitle text-muted">Description</h6>
<p class="card-text">{{ ad.description }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { AdvertisementListComponent } from './advertisement-list.component';

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

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

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

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Component, OnInit } from '@angular/core';
import { Advertisement } from '../advertisement';
import { AdvertisementService } from '../advertisement.service';
import { CommonModule } from '@angular/common';

@Component({
selector: 'app-advertisement-list',
standalone: true,
imports:[CommonModule],
templateUrl: './advertisement-list.component.html',
styleUrls: ['./advertisement-list.component.css']
})
export class AdvertisementListComponent implements OnInit {
advertisements: Advertisement[] = [];

constructor(private advertisementService: AdvertisementService) {}

ngOnInit() {
this.loadAdvertisements();
}

loadAdvertisements() {
this.advertisementService.getAllAdvertisements().subscribe({
next: (response) => {
this.advertisements = response.resources;
},
error: (err) => {
console.error('Error al cargar los anuncios:', err);
}
});
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<div *ngIf="isAuthorized" class="container mt-5 w-50 p-3">
<div class="alert alert-success" role="alert">
You are authorized to create advertisement.
</div>
</div>
<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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { CreateAdvertisementComponent } from './create-advertisement.component';

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

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

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

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { User } from '../../login-basic/user';
import { Apartment } from '../../apartment/apartment';
import { AuthenticationBasicService } from '../../login-basic/authentication-basic.service';
import { ErrorMessageService } from '../../error-handler/error-message.service';

@Component({
selector: 'app-create-advertisement',
standalone: true,imports: [FormsModule, CommonModule],
templateUrl: './create-advertisement.component.html',
styleUrl: './create-advertisement.component.css'
})
export class CreateAdvertisementComponent implements OnInit{
public apartment: Apartment = new Apartment();
public user: User = new User();
public isAuthorized: boolean = false;

constructor(
private authenticationService: AuthenticationBasicService,
private errorMessageService: ErrorMessageService,
) {}

ngOnInit(): void {
this.user = this.authenticationService.getCurrentUser();
this.isAuthorized = this.isAuthorised();
}

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

}
Loading

0 comments on commit bebd8a8

Please sign in to comment.