diff --git a/angular/src/app/app.component.html b/angular/src/app/app.component.html index fbf5771..ab45df1 100644 --- a/angular/src/app/app.component.html +++ b/angular/src/app/app.component.html @@ -5,6 +5,8 @@ + + diff --git a/angular/src/app/app.module.ts b/angular/src/app/app.module.ts index c4cbfef..9a7da97 100644 --- a/angular/src/app/app.module.ts +++ b/angular/src/app/app.module.ts @@ -12,6 +12,7 @@ import { SearchComponent } from './search/search.component'; import { CommonModule } from '@angular/common'; import { ContactformComponent } from './contactform/contactform.component'; import { FormsModule } from '@angular/forms'; +import { FindAdvertisementComponent } from './find-advertisement/find-advertisement.component'; @@ -24,7 +25,8 @@ import { FormsModule } from '@angular/forms'; PropertyListComponent, UserAdvertisementComponent, SearchComponent, - ContactformComponent + ContactformComponent, + FindAdvertisementComponent // PropertyDetailsComponent ], diff --git a/angular/src/app/find-advertisement/find-advertisement.component.css b/angular/src/app/find-advertisement/find-advertisement.component.css new file mode 100644 index 0000000..e69de29 diff --git a/angular/src/app/find-advertisement/find-advertisement.component.html b/angular/src/app/find-advertisement/find-advertisement.component.html new file mode 100644 index 0000000..fc577c9 --- /dev/null +++ b/angular/src/app/find-advertisement/find-advertisement.component.html @@ -0,0 +1 @@ +

find-advertisement works!

diff --git a/angular/src/app/find-advertisement/find-advertisement.component.spec.ts b/angular/src/app/find-advertisement/find-advertisement.component.spec.ts new file mode 100644 index 0000000..4f040fb --- /dev/null +++ b/angular/src/app/find-advertisement/find-advertisement.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FindAdvertisementComponent } from './find-advertisement.component'; + +describe('FindAdvertisementComponent', () => { + let component: FindAdvertisementComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [FindAdvertisementComponent] + }); + fixture = TestBed.createComponent(FindAdvertisementComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/angular/src/app/find-advertisement/find-advertisement.component.ts b/angular/src/app/find-advertisement/find-advertisement.component.ts new file mode 100644 index 0000000..b1288ea --- /dev/null +++ b/angular/src/app/find-advertisement/find-advertisement.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-find-advertisement', + templateUrl: './find-advertisement.component.html', + styleUrls: ['./find-advertisement.component.css'] +}) +export class FindAdvertisementComponent { + +} diff --git a/angular/src/app/form/form.component.css b/angular/src/app/form/form.component.css index 3fd5761..7a4deba 100644 --- a/angular/src/app/form/form.component.css +++ b/angular/src/app/form/form.component.css @@ -1,3 +1,7 @@ +.container { + padding-left: 10px; + padding-right: 10px; +} .form-container { display: flex; flex-direction: column; diff --git a/angular/src/app/form/form.component.html b/angular/src/app/form/form.component.html index f677121..0edd8f8 100644 --- a/angular/src/app/form/form.component.html +++ b/angular/src/app/form/form.component.html @@ -1,3 +1,4 @@ +

Add new property

@@ -9,3 +10,4 @@

Add new property

+
diff --git a/angular/src/app/home/home.component.css b/angular/src/app/home/home.component.css index e69de29..6587385 100644 --- a/angular/src/app/home/home.component.css +++ b/angular/src/app/home/home.component.css @@ -0,0 +1,4 @@ +.container { + padding-left: 10px; + padding-right: 10px; +} diff --git a/angular/src/app/login/login.component.css b/angular/src/app/login/login.component.css index e69de29..6587385 100644 --- a/angular/src/app/login/login.component.css +++ b/angular/src/app/login/login.component.css @@ -0,0 +1,4 @@ +.container { + padding-left: 10px; + padding-right: 10px; +} diff --git a/angular/src/app/property-details/property-details.component.html b/angular/src/app/property-details/property-details.component.html index d239657..8df98ff 100644 --- a/angular/src/app/property-details/property-details.component.html +++ b/angular/src/app/property-details/property-details.component.html @@ -1,3 +1,4 @@ +

Details

{{ property.title }}

@@ -45,6 +46,6 @@

{{ property.title }}

Toilet: {{ property.toilet }}

- +
diff --git a/angular/src/app/property-list/property-list.component.html b/angular/src/app/property-list/property-list.component.html index fb3bd79..fece73a 100644 --- a/angular/src/app/property-list/property-list.component.html +++ b/angular/src/app/property-list/property-list.component.html @@ -8,7 +8,8 @@

Properties

- + + diff --git a/angular/src/app/property-list/property-list.component.ts b/angular/src/app/property-list/property-list.component.ts index 8839545..fd9d968 100644 --- a/angular/src/app/property-list/property-list.component.ts +++ b/angular/src/app/property-list/property-list.component.ts @@ -44,7 +44,7 @@ export class PropertyListComponent implements OnInit { selectedProperty: Property | null = null; showContactForm: boolean = false; // Define the showContactForm property selectedCity: string = ''; - maxRent: number = 1500; + maxRent: number = 0; selectedGender: string = ''; id: number = 2; distinctCities: string[] = []; @@ -52,6 +52,7 @@ export class PropertyListComponent implements OnInit { topN: number = 10; currentPage = 1; + minRent: number = 0; constructor( private http: HttpClient, private router: Router, @@ -111,7 +112,7 @@ export class PropertyListComponent implements OnInit { (data: Page) => { console.log(data); // Log the API response this.properties = data; - this.properties.content = this.properties.content.slice(0, 100); + this.properties.content = this.properties.content.slice(0, 1000); }, (error) => { console.error('Error retrieving properties:', error); @@ -131,7 +132,9 @@ export class PropertyListComponent implements OnInit { if (this.maxRent) { params.maxRent = this.maxRent; } - + if (this.minRent) { + params.minRent = this.minRent; + } if (this.selectedGender) { params.gender = this.selectedGender; } @@ -149,7 +152,9 @@ export class PropertyListComponent implements OnInit { if (this.selectedCity && this.selectedCity !== 'All Cities' && property.city !== this.selectedCity) { meetsCriteria = false; } - + if (this.minRent && property.rent < this.minRent) { + meetsCriteria = false; + } if (this.maxRent && property.rent > this.maxRent) { meetsCriteria = false; } @@ -161,7 +166,7 @@ export class PropertyListComponent implements OnInit { return meetsCriteria; }); - this.properties.content = this.properties.content.slice(0, 100); + this.properties.content = this.properties.content.slice(0, 1000); // Set the flag to show the filter buttons only after the "Apply Filters" button is clicked this.showFilterButtons = true; @@ -176,13 +181,30 @@ export class PropertyListComponent implements OnInit { filterRentDown(): void { if (this.selectedCity && this.selectedCity !== 'All Cities') { const apiUrl = 'http://localhost:8080/property'; - const params: any = { - city: this.selectedCity - }; + const params: any = {}; + + if (this.selectedCity && this.selectedCity !== 'All Cities') { + params.city = this.selectedCity; + } + + if (this.maxRent) { + params.maxRent = this.maxRent; + } + if (this.minRent) { + params.minRent = this.minRent; + } + if (this.selectedGender) { + params.gender = this.selectedGender; + } // Make the API call with the updated URL and query parameters this.http.get>(apiUrl, { params }).pipe( map((data: Page) => { + // Filter the properties based on rent within the specified range + data.content = data.content.filter(property => property.rent >= this.minRent && property.rent <= this.maxRent); + return data; + }), + tap((data: Page) => { // Sort the properties based on rent in descending order data.content.sort((a, b) => b.rent - a.rent); return data; @@ -199,16 +221,34 @@ export class PropertyListComponent implements OnInit { } } + filterRentUp(): void { if (this.selectedCity && this.selectedCity !== 'All Cities') { const apiUrl = 'http://localhost:8080/property'; - const params: any = { - city: this.selectedCity - }; + const params: any = {}; + + if (this.selectedCity && this.selectedCity !== 'All Cities') { + params.city = this.selectedCity; + } + + if (this.maxRent) { + params.maxRent = this.maxRent; + } + if (this.minRent) { + params.minRent = this.minRent; + } + if (this.selectedGender) { + params.gender = this.selectedGender; + } // Make the API call with the updated URL and query parameters this.http.get>(apiUrl, { params }).pipe( map((data: Page) => { + // Filter the properties based on rent within the specified range + data.content = data.content.filter(property => property.rent >= this.minRent && property.rent <= this.maxRent); + return data; + }), + tap((data: Page) => { // Sort the properties based on rent in ascending order data.content.sort((a, b) => a.rent - b.rent); return data; @@ -224,12 +264,25 @@ export class PropertyListComponent implements OnInit { ).subscribe(); } } + filterSqmUp(): void { if (this.selectedCity && this.selectedCity !== 'All Cities') { const apiUrl = 'http://localhost:8080/property'; - const params: any = { - city: this.selectedCity - }; + const params: any = {}; + + if (this.selectedCity && this.selectedCity !== 'All Cities') { + params.city = this.selectedCity; + } + + if (this.maxRent) { + params.maxRent = this.maxRent; + } + if (this.minRent) { + params.minRent = this.minRent; + } + if (this.selectedGender) { + params.gender = this.selectedGender; + } // Make the API call with the updated URL and query parameters this.http.get>(apiUrl, { params }).pipe( @@ -259,9 +312,21 @@ export class PropertyListComponent implements OnInit { filterSqmDown(): void { if (this.selectedCity && this.selectedCity !== 'All Cities') { const apiUrl = 'http://localhost:8080/property'; - const params: any = { - city: this.selectedCity - }; + const params: any = {}; + + if (this.selectedCity && this.selectedCity !== 'All Cities') { + params.city = this.selectedCity; + } + + if (this.maxRent) { + params.maxRent = this.maxRent; + } + if (this.minRent) { + params.minRent = this.minRent; + } + if (this.selectedGender) { + params.gender = this.selectedGender; + } // Make the API call with the updated URL and query parameters this.http.get>(apiUrl, { params }).pipe( @@ -287,5 +352,4 @@ export class PropertyListComponent implements OnInit { ).subscribe(); } } - } diff --git a/angular/src/app/register/register.component.css b/angular/src/app/register/register.component.css index c604101..d4f6673 100644 --- a/angular/src/app/register/register.component.css +++ b/angular/src/app/register/register.component.css @@ -1,3 +1,7 @@ +.container { + padding-left: 10px; + padding-right: 10px; +} .form-container { display: flex; flex-direction: column; diff --git a/angular/src/app/register/register.component.html b/angular/src/app/register/register.component.html index 648c7db..858b4e4 100644 --- a/angular/src/app/register/register.component.html +++ b/angular/src/app/register/register.component.html @@ -1,3 +1,4 @@ +

Register

@@ -8,3 +9,5 @@

Register

+
+ diff --git a/angular/src/app/user-advertisement/user-advertisement.component.css b/angular/src/app/user-advertisement/user-advertisement.component.css index c604101..d4f6673 100644 --- a/angular/src/app/user-advertisement/user-advertisement.component.css +++ b/angular/src/app/user-advertisement/user-advertisement.component.css @@ -1,3 +1,7 @@ +.container { + padding-left: 10px; + padding-right: 10px; +} .form-container { display: flex; flex-direction: column; diff --git a/angular/src/app/user-advertisement/user-advertisement.component.html b/angular/src/app/user-advertisement/user-advertisement.component.html index afed4c9..feb8674 100644 --- a/angular/src/app/user-advertisement/user-advertisement.component.html +++ b/angular/src/app/user-advertisement/user-advertisement.component.html @@ -1,3 +1,4 @@ +

Advertisement

@@ -9,3 +10,4 @@

Advertisement

+
diff --git a/src/main/java/com/example/studenthousing/controller/PropertyController.java b/src/main/java/com/example/studenthousing/controller/PropertyController.java index 82fb70b..db81467 100644 --- a/src/main/java/com/example/studenthousing/controller/PropertyController.java +++ b/src/main/java/com/example/studenthousing/controller/PropertyController.java @@ -5,7 +5,9 @@ import com.example.studenthousing.services.PropertyService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.HashMap; @@ -27,8 +29,10 @@ public class PropertyController { public PropertyController(PropertyService propertyService) { this.propertyService = propertyService; } - @GetMapping("/property") - public ResponseEntity> getPropertyList(@RequestParam(required = false) String city) { + @GetMapping(value = "/property", produces = {MediaType.APPLICATION_JSON_VALUE, "text/csv"}) + public ResponseEntity getPropertyList( + @RequestParam(required = false) String city, + @RequestParam(defaultValue = "json") String format) { Page properties; if (city != null) { properties = propertyService.getPropertiesByCity(city); @@ -36,19 +40,70 @@ public ResponseEntity> getPropertyList(@RequestParam(required = f } else { properties = propertyService.getProperties(); } - return ResponseEntity.ok(properties); + HttpHeaders headers = new HttpHeaders(); + if (format.equalsIgnoreCase("csv")) { + headers.setContentType(MediaType.parseMediaType("text/csv")); + String csvData = convertPropertiesToCSV(properties.getContent()); + return new ResponseEntity<>(csvData, headers, HttpStatus.OK); + } else { + headers.setContentType(MediaType.APPLICATION_JSON); + return new ResponseEntity<>(properties, headers, HttpStatus.OK); + } + } + + private String convertPropertiesToCSV(List properties) { + StringBuilder csvBuilder = new StringBuilder(); + csvBuilder.append("id,external_id,area_sqm,city,cover_image_url,furnish,latitude,longitude,postal_code,property_type,raw_availability,rent,rent_detail,title,additional_costs,deposit,description_non_translated,description_translated,energy_label,gender,internet,is_room_active,kitchen,living,match_age,match_capacity,match_gender,match_languages,match_status,page_description,page_title,pets,registration_costs,roommates,shower,smoking_inside,toilet\n"); + for (Property property : properties) { + csvBuilder.append(property.getId()).append(",") + .append(property.getExternalId()).append(",") + .append(property.getAreaSqm()).append(",") + .append(property.getCity()).append(",") + .append(property.getCoverImageUrl()).append(",") + .append(property.getFurnish()).append(",") + .append(property.getLatitude()).append(",") + .append(property.getLongitude()).append(",") + .append(property.getPostalCode()).append(",") + .append(property.getPropertyType()).append(",") + .append(property.getRawAvailability()).append(",") + .append(property.getRent()).append(",") + .append(property.getRentDetail()).append(",") + .append(property.getTitle()).append(",") + .append(property.getAdditionalCosts()).append(",") + .append(property.getDeposit()).append(",") + .append(property.getDescriptionNonTranslated()).append(",") + .append(property.getDescriptionTranslated()).append(",") + .append(property.getEnergyLabel()).append(",") + .append(property.getGender()).append(",") + .append(property.getInternet()).append(",") + .append(property.getIsRoomActive()).append(",") + .append(property.getKitchen()).append(",") + .append(property.getLiving()).append(",") + .append(property.getMatchAge()).append(",") + .append(property.getMatchCapacity()).append(",") + .append(property.getMatchGender()).append(",") + .append(property.getMatchLanguages()).append(",") + .append(property.getMatchStatus()).append(",") + .append(property.getPageDescription()).append(",") + .append(property.getPageTitle()).append(",") + .append(property.getPets()).append(",") + .append(property.getRegistrationCost()).append(",") + .append(property.getRoommates()).append(",") + .append(property.getShower()).append(",") + .append(property.getSmokingInside()).append(",") + .append(property.getToilet()).append("\n"); + } + return csvBuilder.toString(); } + + @GetMapping("/property/distinct-cities") public ResponseEntity> getDistinctCities() { List cities = propertyService.getDistinctCities(); return ResponseEntity.ok(cities); } - /* @GetMapping("/property/find-all-ids") - public ResponseEntity> findAllIds() { - List propertyIds = propertyService.findById(); - return ResponseEntity.ok(propertyIds); - }*/ + @GetMapping("/property/{id}") public ResponseEntity getPropertiesById(@PathVariable("id") int id) { diff --git a/src/main/java/com/example/studenthousing/services/PropertyService.java b/src/main/java/com/example/studenthousing/services/PropertyService.java index 04d97c7..ca13a07 100644 --- a/src/main/java/com/example/studenthousing/services/PropertyService.java +++ b/src/main/java/com/example/studenthousing/services/PropertyService.java @@ -68,7 +68,7 @@ public Property newProperty(int id, String externalId, int areaSqm, String city, return propertyRepository.save(p); } public Page getProperties() { - Pageable pageable = PageRequest.of(0, 100); + Pageable pageable = PageRequest.of(0, 1000); return propertyRepository.findAll(pageable); } @@ -79,11 +79,11 @@ public List getDistinctCities() { return propertyRepository.findAllDistinctCities(); } public Page getPropertiesByCity(String city) { - Pageable pageable = PageRequest.of(0, 100); + Pageable pageable = PageRequest.of(0, 1000); return propertyRepository.findByCity(city,pageable); } public Page getPropertiesById(int id) { - Pageable pageable = PageRequest.of(0, 100); + Pageable pageable = PageRequest.of(0, 1000); return propertyRepository.findById(id,pageable); } public void test() {