Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix-fav #60

Merged
merged 1 commit into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.mini.pms.configuration;

import lombok.RequiredArgsConstructor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
Expand All @@ -29,12 +29,12 @@ public class SecurityConfig {

private final JwtFilter jwtFilter;
private static final String[] STATIC_RESOURCES = {
"/images/**",
"/js/**",
"/webjars/**",
"/swagger-resources/",
"/swagger-ui/**",
"/v3/api-docs/**"
"/images/**",
"/js/**",
"/webjars/**",
"/swagger-resources/",
"/swagger-ui/**",
"/v3/api-docs/**"
};

@Bean
Expand All @@ -59,13 +59,17 @@ public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws
authorize
.requestMatchers(
contextPath + "/public",
contextPath + "/auth/**",
contextPath + "/files/**",
contextPath + "/properties/**",
contextPath + "/properties"
)
contextPath + "/auth/**"
)
.permitAll()

.requestMatchers(HttpMethod.GET,
contextPath + "/properties/**",
contextPath + "/properties",
contextPath + "/files/**"
)
.permitAll()

.requestMatchers(contextPath + "/admins/**")
.hasAuthority("Admin")
.requestMatchers(contextPath + "/owners/**")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import jakarta.servlet.ServletException;
import jakarta.validation.ValidationException;
import lombok.NonNull;
import lombok.extern.log4j.Log4j2;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
Expand All @@ -23,20 +24,22 @@
import java.util.Map;

@ControllerAdvice
@Log4j2
public class ExceptionControllerAdvice extends ResponseEntityExceptionHandler {

private static final Logger logger = LogManager.getLogger(ExceptionControllerAdvice.class);

@ExceptionHandler({RuntimeException.class, ServletException.class})
public ResponseEntity<ExceptionResponse> handleException(Exception e) {
e.printStackTrace();
log.error(e);
if (e instanceof PlatformException) {
var platform = (PlatformException) e;
e.fillInStackTrace();
logger.error(e.fillInStackTrace());
if (e instanceof PlatformException platform) {
return createResponseEntity(platform.getMessage(), platform.getHttpStatusCode());
} else if (e instanceof AccessDeniedException) {
return createResponseEntity("Access Denied", HttpStatus.FORBIDDEN);
} else if (e instanceof NoResourceFoundException) {
return createResponseEntity("Resource Not Found", HttpStatus.NOT_FOUND);
} else if(e instanceof ValidationException) {
return createResponseEntity(e.getMessage(), HttpStatus.BAD_REQUEST);
}
return createResponseEntity("General Error", HttpStatus.INTERNAL_SERVER_ERROR);
}
Expand Down Expand Up @@ -68,9 +71,4 @@ protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotV
});
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(ValidationException.class)
public ResponseEntity<ExceptionResponse> handleValidationException(ValidationException exception) {
return createResponseEntity(exception.getMessage(), HttpStatus.BAD_REQUEST);
}
}

This file was deleted.

This file was deleted.

11 changes: 6 additions & 5 deletions backend/pms/src/main/java/com/mini/pms/repo/FavoriteRepo.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package com.mini.pms.repo;

import java.util.List;

import com.mini.pms.entity.Favorite;
import com.mini.pms.entity.Member;
import com.mini.pms.entity.Property;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;


import com.mini.pms.entity.Member;
import com.mini.pms.entity.Property;
import java.util.List;
import java.util.Optional;

public interface FavoriteRepo extends JpaRepository<Favorite,Long> {
@Query("SELECT p FROM Favorite f JOIN f.member u JOIN f.property p WHERE u.id = :memberId")
Expand All @@ -24,5 +23,7 @@ public interface FavoriteRepo extends JpaRepository<Favorite,Long> {

List<Favorite> findByMemberId(long memberId);

Optional<Favorite> findByMemberAndProperty(Member member, Property property);


}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.mini.pms.service.impl;

import com.mini.pms.customexception.MemberNotFoundException;
import com.mini.pms.customexception.PropertyNotFoundException;
import com.mini.pms.customexception.PlatformException;
import com.mini.pms.entity.Favorite;
import com.mini.pms.entity.Member;
import com.mini.pms.entity.Property;
Expand All @@ -11,32 +10,34 @@
import com.mini.pms.service.PropertyService;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class FavoriteServiceImpl implements FavoriteService{
public class FavoriteServiceImpl implements FavoriteService {
@Autowired
private FavoriteRepo favoriteRepo;
@Autowired
private MemberService memberService;
@Autowired
private PropertyService propertyService;

@Override
public void addFavorite(long propertyId, long memberId) {
// Retrieve the Member and Property entities using the IDs provided in the DTO
Member member = memberService.findById(memberId);
Property property = propertyService.findById(propertyId);
// Check if the member exists
if (member == null) {
throw new MemberNotFoundException("Member with ID " + memberId + " not found.");
}
// Check if the property exists
if (property == null) {
throw new PropertyNotFoundException("Property with ID " + propertyId + " not found.");

var existingFav = favoriteRepo.findByMemberAndProperty(member, property);

if (existingFav.isPresent()) {
throw new PlatformException("Favorite already exist", HttpStatus.BAD_REQUEST);
}


// At this point, both member and property exist
// Create a new Favorite entity and set its member and property
Favorite favorite = new Favorite();
Expand Down Expand Up @@ -71,6 +72,7 @@ public List<Property> getFavoriteByMemberId(long memberId) {
public List<Member> getFavoritePropertyId(long propertyId) {
return favoriteRepo.findFavoritesUsersByPropertyId(propertyId);
}

@Override
public List<Property> findFavoritesByMemberId(long memberId) {
List<Favorite> favorites = favoriteRepo.findByMemberId(memberId);
Expand All @@ -79,10 +81,10 @@ public List<Property> findFavoritesByMemberId(long memberId) {
.collect(Collectors.toList());
}

// @Override
// public void unFavorite(long favoriteId) {
// favoriteRepo.deleteById(favoriteId);
// }
public Favorite findFavoriteByMemberAndProperty(Member member, Property property) {
return favoriteRepo.findByMemberAndProperty(member, property)
.orElseThrow(() -> new PlatformException("Not Found", HttpStatus.NOT_FOUND));
}



}
14 changes: 10 additions & 4 deletions frontend/src/components/Property.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useState } from "react";
import { Card, Button, Badge } from "react-bootstrap";
import { MdFavoriteBorder, MdOutlineFavorite } from "react-icons/md";
import { Link } from "react-router-dom";
Expand All @@ -19,13 +19,18 @@ const Property = ({
const addFavorite = async (id) => {
api.post(`favorites/${id}`).then((res) => {
console.log(res);
setIsFav(true);
});
};
const removeFavorite = (id) => {
api.delete(`favorites/${id}`).then((res) => {
console.log(res);
setIsFav(false);
});
};

const [isFav, setIsFav] = useState(favorite);

return (
<Card>
<Card.Img variant="top" src={pictures[0]} height={300} img-fluid />
Expand All @@ -50,14 +55,15 @@ const Property = ({
}>{offerStatus}</Badge>
</span>


<Button
variant={favorite ? "danger" : "primary"}
variant={isFav ? "danger" : "primary"}
onClick={() => {
favorite ? removeFavorite(id) : addFavorite(id);
isFav ? removeFavorite(id) : addFavorite(id);
refetch();
}}
>
{favorite ? <MdOutlineFavorite /> : <MdFavoriteBorder />}
{isFav ? <MdOutlineFavorite /> : <MdFavoriteBorder />}
</Button>
{
viewOffer && (
Expand Down
Loading