Skip to content
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
@@ -0,0 +1,95 @@
package kw.zeropick.product.controller;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import kw.zeropick.payload.ApiResponse;
import kw.zeropick.product.dto.ProductDto;
import kw.zeropick.product.dto.ProductRecentDto;
import kw.zeropick.product.service.ProductRecentService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/recent")
@RequiredArgsConstructor
public class ProductRecentController {
private final ProductRecentService recentService;

@PostMapping("/{productId}")
public ResponseEntity<ApiResponse> addRecentProduct(
@PathVariable Long productId,
HttpServletRequest request,
HttpServletResponse response
) {
try {
// 쿠키 값 가져오기
String cookieValue = getCookieValue(request, "recentProducts");

// 서비스 호출
String updatedCookieValue = recentService.addRecentProduct(productId, cookieValue);

// 쿠키 저장
Cookie cookie = new Cookie("recentProducts", updatedCookieValue);
cookie.setPath("/");
cookie.setHttpOnly(true);
cookie.setMaxAge(7 * 24 * 60 * 60); // 7일
response.addCookie(cookie);

return ResponseEntity.ok(
ApiResponse.builder()
.check(true)
.information("상품이 최근 본 목록에 추가되었습니다.")
.build()
);
} catch (Exception e) {
return ResponseEntity.internalServerError().body(
ApiResponse.builder()
.check(false)
.information(e.getMessage())
.build()
);
}
}

@GetMapping
public ResponseEntity<ApiResponse> getRecentProducts(HttpServletRequest request) {
try {
String cookieValue = getCookieValue(request, "recentProducts");

// 서비스 호출
List<ProductRecentDto> recentProducts = recentService.getRecentProducts(cookieValue);

return ResponseEntity.ok(
ApiResponse.builder()
.check(true)
.information(recentProducts)
.build()
);
} catch (Exception e) {
return ResponseEntity.internalServerError().body(
ApiResponse.builder()
.check(false)
.information(e.getMessage())
.build()
);
}
}

private String getCookieValue(HttpServletRequest request, String cookieName) {
if (request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
if (cookieName.equals(cookie.getName())) {
return cookie.getValue();
}
}
}
return null;
}
}
16 changes: 16 additions & 0 deletions src/main/java/kw/zeropick/product/dto/ProductRecentDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package kw.zeropick.product.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@AllArgsConstructor
@Builder
public class ProductRecentDto {
private Long id;

private String productName;

private String imageUrl;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package kw.zeropick.product.service;

import java.util.List;
import kw.zeropick.product.dto.ProductDto;
import kw.zeropick.product.dto.ProductRecentDto;

public interface ProductRecentService {
List<ProductRecentDto> getRecentProducts(String cookieValue) throws Exception;
String addRecentProduct(Long productId, String cookieValue) throws Exception;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package kw.zeropick.product.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import kw.zeropick.product.domain.Product;
import kw.zeropick.product.dto.ProductDto;
import kw.zeropick.product.dto.ProductRecentDto;
import kw.zeropick.product.repository.ProductJpaRepository;
import kw.zeropick.product.service.ProductRecentService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ProductRecentServiceImpl implements ProductRecentService {
private final ProductJpaRepository productJpaRepository;
private final ObjectMapper objectMapper;
private final ProductService productService;

@Override
public List<ProductRecentDto> getRecentProducts(String cookieValue) throws Exception {
if (cookieValue == null || cookieValue.isEmpty()) {
return new ArrayList<>();
}
String decodedValue = URLDecoder.decode(cookieValue, StandardCharsets.UTF_8);
return objectMapper.readValue(decodedValue, new TypeReference<>() {});
}

@Override
public String addRecentProduct(Long productId, String cookieValue) throws Exception {
// 현재 상품 정보 가져오기
ProductRecentDto productDto = toProductDto(productService.productDetail(productId));

// 기존 쿠키 값 디코딩
List<ProductRecentDto> recentProducts = getRecentProducts(cookieValue);

// 기존 상품 제거 후 추가
recentProducts.removeIf(product -> product.getId().equals(productId));
recentProducts.add(productDto);

// 최대 3개 유지
if (recentProducts.size() > 3) {
recentProducts.remove(0);
}

// JSON 문자열로 변환 및 인코딩
String jsonValue = objectMapper.writeValueAsString(recentProducts);
return URLEncoder.encode(jsonValue, StandardCharsets.UTF_8);
}

private ProductRecentDto toProductDto(ProductDto product) {
return ProductRecentDto.builder()
.id(product.getId())
.productName(product.getProductName())
.imageUrl(product.getImageUrl())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public ProductDto productDetail(Long productId) {

ProductDto productDto = toProductDto(product, null);
List<ArtificialSweetDto> artificialSweetDtos = new ArrayList<>();
if(product.getIngredient().getAllulose() != 0){
if(product.getIngredient().getAllulose() != null && product.getIngredient().getAllulose() != 0){
ArtificialSweetDto artificialSweetDto = ArtificialSweetDto.builder()
.sweetName("알룰로오스")
.sweetDetail("알룰로오스 설명")
Expand All @@ -62,7 +62,7 @@ public ProductDto productDetail(Long productId) {
.build();
artificialSweetDtos.add(artificialSweetDto);
}
if(product.getIngredient().getErythritol() != 0){
if(product.getIngredient().getErythritol() != null && product.getIngredient().getErythritol() != 0){
ArtificialSweetDto artificialSweetDto = ArtificialSweetDto.builder()
.sweetName("에리트리톨")
.sweetDetail("에리트리톨 설명")
Expand Down