diff --git a/backend/src/main/java/com/funeat/product/domain/Category.java b/backend/src/main/java/com/funeat/product/domain/Category.java
index 03d1d4f52..5d6c62a08 100644
--- a/backend/src/main/java/com/funeat/product/domain/Category.java
+++ b/backend/src/main/java/com/funeat/product/domain/Category.java
@@ -1,11 +1,6 @@
package com.funeat.product.domain;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
+import javax.persistence.*;
@Entity
public class Category {
@@ -19,12 +14,15 @@ public class Category {
@Enumerated(EnumType.STRING)
private CategoryType type;
+ private String image;
+
protected Category() {
}
- public Category(final String name, final CategoryType type) {
+ public Category(final String name, final CategoryType type, final String image) {
this.name = name;
this.type = type;
+ this.image = image;
}
public Long getId() {
@@ -38,4 +36,8 @@ public String getName() {
public CategoryType getType() {
return type;
}
+
+ public String getImage() {
+ return image;
+ }
}
diff --git a/backend/src/main/java/com/funeat/product/dto/CategoryResponse.java b/backend/src/main/java/com/funeat/product/dto/CategoryResponse.java
index ebf70e602..3ea9e59a5 100644
--- a/backend/src/main/java/com/funeat/product/dto/CategoryResponse.java
+++ b/backend/src/main/java/com/funeat/product/dto/CategoryResponse.java
@@ -6,14 +6,16 @@ public class CategoryResponse {
private final Long id;
private final String name;
+ private final String image;
- public CategoryResponse(final Long id, final String name) {
+ public CategoryResponse(final Long id, final String name, final String image) {
this.id = id;
this.name = name;
+ this.image = image;
}
public static CategoryResponse toResponse(final Category category) {
- return new CategoryResponse(category.getId(), category.getName());
+ return new CategoryResponse(category.getId(), category.getName(), category.getImage());
}
public Long getId() {
@@ -23,4 +25,8 @@ public Long getId() {
public String getName() {
return name;
}
+
+ public String getImage() {
+ return image;
+ }
}
diff --git a/backend/src/test/java/com/funeat/fixture/CategoryFixture.java b/backend/src/test/java/com/funeat/fixture/CategoryFixture.java
index b41401ce3..9d6da56ab 100644
--- a/backend/src/test/java/com/funeat/fixture/CategoryFixture.java
+++ b/backend/src/test/java/com/funeat/fixture/CategoryFixture.java
@@ -7,42 +7,42 @@
public class CategoryFixture {
public static Category 카테고리_간편식사_생성() {
- return new Category("간편식사", CategoryType.FOOD);
+ return new Category("간편식사", CategoryType.FOOD, "siksa.jpeg");
}
public static Category 카테고리_즉석조리_생성() {
- return new Category("즉석조리", CategoryType.FOOD);
+ return new Category("즉석조리", CategoryType.FOOD, "direct.jpeg");
}
public static Category 카테고리_과자류_생성() {
- return new Category("과자류", CategoryType.FOOD);
+ return new Category("과자류", CategoryType.FOOD, "snack.jpeg");
}
public static Category 카테고리_아이스크림_생성() {
- return new Category("아이스크림", CategoryType.FOOD);
+ return new Category("아이스크림", CategoryType.FOOD, "ice.jpeg");
}
public static Category 카테고리_식품_생성() {
- return new Category("식품", CategoryType.FOOD);
+ return new Category("식품", CategoryType.FOOD, "food.jpeg");
}
public static Category 카테고리_음료_생성() {
- return new Category("음료", CategoryType.FOOD);
+ return new Category("음료", CategoryType.FOOD, "drink.jpeg");
}
public static Category 카테고리_CU_생성() {
- return new Category("CU", CategoryType.STORE);
+ return new Category("CU", CategoryType.STORE, "cu.jpeg");
}
public static Category 카테고리_GS25_생성() {
- return new Category("GS25", CategoryType.STORE);
+ return new Category("GS25", CategoryType.STORE, "gs25.jpeg");
}
public static Category 카테고리_EMART24_생성() {
- return new Category("EMART24", CategoryType.STORE);
+ return new Category("EMART24", CategoryType.STORE, "emart.jpeg");
}
public static Category 카테고리_세븐일레븐_생성() {
- return new Category("세븐일레븐", CategoryType.STORE);
+ return new Category("세븐일레븐", CategoryType.STORE, "seven.jpeg");
}
}
diff --git a/backend/src/test/java/com/funeat/recipe/application/RecipeServiceTest.java b/backend/src/test/java/com/funeat/recipe/application/RecipeServiceTest.java
index f68b15d33..1b9b09aba 100644
--- a/backend/src/test/java/com/funeat/recipe/application/RecipeServiceTest.java
+++ b/backend/src/test/java/com/funeat/recipe/application/RecipeServiceTest.java
@@ -1,28 +1,5 @@
package com.funeat.recipe.application;
-import static com.funeat.fixture.CategoryFixture.카테고리_간편식사_생성;
-import static com.funeat.fixture.CategoryFixture.카테고리_즉석조리_생성;
-import static com.funeat.fixture.ImageFixture.여러_이미지_생성;
-import static com.funeat.fixture.MemberFixture.멤버_멤버1_생성;
-import static com.funeat.fixture.MemberFixture.멤버_멤버2_생성;
-import static com.funeat.fixture.MemberFixture.멤버_멤버3_생성;
-import static com.funeat.fixture.PageFixture.페이지요청_생성_시간_내림차순_생성;
-import static com.funeat.fixture.PageFixture.페이지요청_생성_시간_오름차순_생성;
-import static com.funeat.fixture.PageFixture.페이지요청_좋아요_내림차순_생성;
-import static com.funeat.fixture.ProductFixture.레시피_안에_들어가는_상품_생성;
-import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격1000원_평점2점_생성;
-import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격1000원_평점5점_생성;
-import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격2000원_평점1점_생성;
-import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격2000원_평점3점_생성;
-import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격3000원_평점4점_생성;
-import static com.funeat.fixture.RecipeFixture.레시피_생성;
-import static com.funeat.fixture.RecipeFixture.레시피이미지_생성;
-import static com.funeat.fixture.RecipeFixture.레시피좋아요요청_생성;
-import static com.funeat.fixture.RecipeFixture.레시피추가요청_생성;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.assertj.core.api.SoftAssertions.assertSoftly;
-
import com.funeat.common.ServiceTest;
import com.funeat.common.dto.PageDto;
import com.funeat.member.domain.Member;
@@ -38,12 +15,24 @@
import com.funeat.recipe.dto.RecipeDetailResponse;
import com.funeat.recipe.dto.RecipeDto;
import com.funeat.recipe.exception.RecipeException.RecipeNotFoundException;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
+
+import static com.funeat.fixture.CategoryFixture.카테고리_간편식사_생성;
+import static com.funeat.fixture.CategoryFixture.카테고리_즉석조리_생성;
+import static com.funeat.fixture.ImageFixture.여러_이미지_생성;
+import static com.funeat.fixture.MemberFixture.*;
+import static com.funeat.fixture.PageFixture.*;
+import static com.funeat.fixture.ProductFixture.*;
+import static com.funeat.fixture.RecipeFixture.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.SoftAssertions.assertSoftly;
@SuppressWarnings("NonAsciiCharacters")
class RecipeServiceTest extends ServiceTest {
@@ -88,7 +77,7 @@ class create_성공_테스트 {
@Test
void 레시피의_상세_정보를_조회할_수_있다() {
// given
- final var category = 카테고리_추가_요청(new Category("간편식사", CategoryType.FOOD));
+ final var category = 카테고리_추가_요청(new Category("간편식사", CategoryType.FOOD, "siksa.jpeg"));
final var product1 = new Product("불닭볶음면", 1000L, "image.png", "엄청 매운 불닭", category);
final var product2 = new Product("참치 삼김", 2000L, "image.png", "담백한 참치마요 삼김", category);
final var product3 = new Product("스트링 치즈", 1500L, "image.png", "고소한 치즈", category);
diff --git a/frontend/src/components/Common/Carousel/Carousel.tsx b/frontend/src/components/Common/Carousel/Carousel.tsx
index 4fa1839f4..5f7c3ad23 100644
--- a/frontend/src/components/Common/Carousel/Carousel.tsx
+++ b/frontend/src/components/Common/Carousel/Carousel.tsx
@@ -7,12 +7,12 @@ interface CarouselProps {
carouselList: CarouselChildren[];
}
-const CAROUSEL_WIDTH = window.innerWidth;
-
const Carousel = ({ carouselList }: CarouselProps) => {
const extendedCarouselList = [...carouselList, carouselList[0]];
const [currentIndex, setCurrentIndex] = useState(0);
+ const CAROUSEL_WIDTH = window.innerWidth;
+
const showNextSlide = () => {
setCurrentIndex((prev) => (prev === carouselList.length ? 0 : prev + 1));
};
@@ -25,9 +25,16 @@ const Carousel = ({ carouselList }: CarouselProps) => {
return (
-
+
{extendedCarouselList.map(({ id, children }) => (
- {children}
+
+ {children}
+
))}
@@ -44,13 +51,10 @@ const CarouselContainer = styled.div`
overflow: hidden;
`;
-const CarouselWrapper = styled.ul<{ currentIndex: number }>`
+const CarouselWrapper = styled.ul`
display: flex;
- transform: ${({ currentIndex }) => 'translateX(-' + currentIndex * CAROUSEL_WIDTH + 'px)'};
- transition: ${({ currentIndex }) => (currentIndex === length - 1 ? '' : 'all 0.5s ease-in-out')};
`;
const CarouselItem = styled.li`
- width: ${CAROUSEL_WIDTH}px;
height: fit-content;
`;
diff --git a/frontend/src/components/Common/CategoryItem/CategoryItem.tsx b/frontend/src/components/Common/CategoryItem/CategoryItem.tsx
index a16889758..4ce54ce72 100644
--- a/frontend/src/components/Common/CategoryItem/CategoryItem.tsx
+++ b/frontend/src/components/Common/CategoryItem/CategoryItem.tsx
@@ -34,7 +34,7 @@ const ImageWrapper = styled.div`
border-radius: 10px;
background: ${({ theme }) => theme.colors.white};
- img {
+ & > img {
width: 100%;
height: auto;
object-fit: cover;
@@ -44,5 +44,5 @@ const ImageWrapper = styled.div`
const CategoryName = styled.p`
margin-top: 10px;
font-weight: 600;
- font-size: 0.8rem;
+ font-size: ${({ theme }) => theme.fontSizes.xs};
`;
diff --git a/frontend/src/components/Common/CategoryList/CategoryList.tsx b/frontend/src/components/Common/CategoryList/CategoryList.tsx
index cb239db02..675ab02fe 100644
--- a/frontend/src/components/Common/CategoryList/CategoryList.tsx
+++ b/frontend/src/components/Common/CategoryList/CategoryList.tsx
@@ -4,38 +4,25 @@ import styled from 'styled-components';
import CategoryItem from '../CategoryItem/CategoryItem';
-import { MENU_IMAGES, MENU_NAME, STORE_IMAGES, STORE_NAMES } from '@/constants';
+import { CATEGORY_TYPE } from '@/constants';
+import { useCategoryQuery } from '@/hooks/queries/product';
-const MENU_LENGTH = 5;
-const STORE_LENGTH = 4;
+interface CategoryListProps {
+ menuVariant: keyof typeof CATEGORY_TYPE;
+}
-const menuList = Array.from({ length: MENU_LENGTH }, (_, index) => ({
- name: MENU_NAME[index],
- image: MENU_IMAGES[index],
-}));
+const CategoryList = ({ menuVariant }: CategoryListProps) => {
+ const { data: categories } = useCategoryQuery(CATEGORY_TYPE[menuVariant]);
-const storeList = Array.from({ length: STORE_LENGTH }, (_, index) => ({
- name: STORE_NAMES[index],
- image: STORE_IMAGES[index],
-}));
-
-const CategoryList = () => {
return (
-
- {menuList.map((menu, index) => (
-
+
+ {categories.map((menu) => (
+
))}
-
-
- {storeList.map((menu, index) => (
-
-
-
- ))}
-
+
);
};
@@ -57,12 +44,7 @@ const CategoryListContainer = styled.div`
}
`;
-const MenuListWrapper = styled.div`
- display: flex;
- gap: 20px;
-`;
-
-const StoreListWrapper = styled.div`
+const CategoryListWrapper = styled.div`
display: flex;
gap: 20px;
`;
diff --git a/frontend/src/components/Layout/DefaultLayout.tsx b/frontend/src/components/Layout/DefaultLayout.tsx
index 4daf634ee..39f1f8cff 100644
--- a/frontend/src/components/Layout/DefaultLayout.tsx
+++ b/frontend/src/components/Layout/DefaultLayout.tsx
@@ -25,7 +25,6 @@ const DefaultLayoutContainer = styled.div`
const MainWrapper = styled.main`
position: relative;
height: calc(100% - 120px);
- padding: 0 20px;
overflow-x: hidden;
overflow-y: auto;
`;
diff --git a/frontend/src/components/Layout/SimpleHeaderLayout.tsx b/frontend/src/components/Layout/SimpleHeaderLayout.tsx
index c6c469169..4f17b93a2 100644
--- a/frontend/src/components/Layout/SimpleHeaderLayout.tsx
+++ b/frontend/src/components/Layout/SimpleHeaderLayout.tsx
@@ -25,7 +25,7 @@ const SimpleHeaderLayoutContainer = styled.div`
const MainWrapper = styled.main`
position: relative;
height: calc(100% - 120px);
- padding: 20px;
+ padding: 20px 20px 0;
overflow-x: hidden;
overflow-y: auto;
`;
diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts
index 2cd47c742..81b964c6c 100644
--- a/frontend/src/constants/index.ts
+++ b/frontend/src/constants/index.ts
@@ -67,22 +67,3 @@ export const ENVIRONMENT = window.location.href.includes('dev') ? 'dev' : 'prod'
export const IMAGE_URL =
ENVIRONMENT === 'dev' ? process.env.S3_DEV_CLOUDFRONT_PATH : process.env.S3_PROD_CLOUDFRONT_PATH;
-
-export const MENU_NAME = ['간편식사', '과자류', '아이스크림', '식품', '음료'] as const;
-
-export const STORE_NAMES = ['CU', 'GS25', '이마트24', '세븐일레븐'] as const;
-
-export const MENU_IMAGES = [
- `${IMAGE_URL}food.jpeg`,
- `${IMAGE_URL}snack.jpeg`,
- `${IMAGE_URL}icecream.jpeg`,
- `${IMAGE_URL}ramen.jpeg`,
- `${IMAGE_URL}tea.jpeg`,
-];
-
-export const STORE_IMAGES = [
- `${IMAGE_URL}cu.jpg`,
- `${IMAGE_URL}gs.png`,
- `${IMAGE_URL}emart24.png`,
- `${IMAGE_URL}seven.png`,
-];
diff --git a/frontend/src/mocks/data/foodCategory.json b/frontend/src/mocks/data/foodCategory.json
index 81d4adc8a..daff82ce0 100644
--- a/frontend/src/mocks/data/foodCategory.json
+++ b/frontend/src/mocks/data/foodCategory.json
@@ -1,7 +1,7 @@
[
- { "id": 1, "name": "간편식사" },
- { "id": 2, "name": "과자류" },
- { "id": 3, "name": "아이스크림" },
- { "id": 4, "name": "식품" },
- { "id": 5, "name": "음료" }
+ { "id": 1, "name": "간편식사", "image": "https://tqklhszfkvzk6518638.cdn.ntruss.com/product/8801771029052.jpg" },
+ { "id": 2, "name": "과자류", "image": "https://tqklhszfkvzk6518638.cdn.ntruss.com/product/8801771029052.jpg" },
+ { "id": 3, "name": "아이스크림", "image": "https://tqklhszfkvzk6518638.cdn.ntruss.com/product/8801771029052.jpg" },
+ { "id": 4, "name": "식품", "image": "https://tqklhszfkvzk6518638.cdn.ntruss.com/product/8801771029052.jpg" },
+ { "id": 5, "name": "음료", "image": "https://tqklhszfkvzk6518638.cdn.ntruss.com/product/8801771029052.jpg" }
]
diff --git a/frontend/src/mocks/data/storeCategory.json b/frontend/src/mocks/data/storeCategory.json
index e2242d83e..b9c7c9445 100644
--- a/frontend/src/mocks/data/storeCategory.json
+++ b/frontend/src/mocks/data/storeCategory.json
@@ -1,6 +1,6 @@
[
- { "id": 6, "name": "CU" },
- { "id": 7, "name": "GS25" },
- { "id": 8, "name": "이마트24" },
- { "id": 9, "name": "세븐일레븐" }
+ { "id": 6, "name": "CU", "image": "https://tqklhszfkvzk6518638.cdn.ntruss.com/product/8801771029052.jpg" },
+ { "id": 7, "name": "GS25", "image": "https://tqklhszfkvzk6518638.cdn.ntruss.com/product/8801771029052.jpg" },
+ { "id": 8, "name": "이마트24", "image": "https://tqklhszfkvzk6518638.cdn.ntruss.com/product/8801771029052.jpg" },
+ { "id": 9, "name": "세븐일레븐", "image": "https://tqklhszfkvzk6518638.cdn.ntruss.com/product/8801771029052.jpg" }
]
diff --git a/frontend/src/pages/HomePage.tsx b/frontend/src/pages/HomePage.tsx
index 0e56c8fe1..306285fb1 100644
--- a/frontend/src/pages/HomePage.tsx
+++ b/frontend/src/pages/HomePage.tsx
@@ -27,18 +27,19 @@ const HomePage = () => {
-
+
-
+
🍯 꿀조합 랭킹
@@ -48,9 +49,9 @@ const HomePage = () => {
-
+
-
+
👑 상품 랭킹
@@ -60,9 +61,9 @@ const HomePage = () => {
-
+
-
+
📝 리뷰 랭킹
@@ -72,7 +73,7 @@ const HomePage = () => {
-
+
>
);
@@ -83,3 +84,7 @@ export default HomePage;
const Banner = styled.img`
width: 100%;
`;
+
+const SectionWrapper = styled.section`
+ padding: 0 20px;
+`;
diff --git a/frontend/src/pages/MemberPage.tsx b/frontend/src/pages/MemberPage.tsx
index 129e65f53..bb5fca6bb 100644
--- a/frontend/src/pages/MemberPage.tsx
+++ b/frontend/src/pages/MemberPage.tsx
@@ -1,6 +1,7 @@
import { Spacing } from '@fun-eat/design-system';
import { useQueryErrorResetBoundary } from '@tanstack/react-query';
import { Suspense } from 'react';
+import styled from 'styled-components';
import { ErrorBoundary, ErrorComponent, Loading, NavigableSectionTitle } from '@/components/Common';
import { MembersInfo, MemberReviewList, MemberRecipeList } from '@/components/Members';
@@ -10,7 +11,7 @@ const MemberPage = () => {
const { reset } = useQueryErrorResetBoundary();
return (
- <>
+
}>
@@ -30,8 +31,12 @@ const MemberPage = () => {
- >
+
);
};
export default MemberPage;
+
+const MemberPageContainer = styled.div`
+ padding: 20px 20px 0;
+`;
diff --git a/frontend/src/pages/MemberRecipePage.tsx b/frontend/src/pages/MemberRecipePage.tsx
index c4dafb772..90bddc44b 100644
--- a/frontend/src/pages/MemberRecipePage.tsx
+++ b/frontend/src/pages/MemberRecipePage.tsx
@@ -11,7 +11,7 @@ const MemberRecipePage = () => {
const memberRecipeRef = useRef(null);
return (
-
+
@@ -20,13 +20,15 @@ const MemberRecipePage = () => {
-
+
+
);
};
export default MemberRecipePage;
-const MebmberRecipePageContainer = styled.div`
+const MemberRecipePageContainer = styled.div`
height: 100%;
+ padding: 20px 20px 0;
overflow-y: auto;
`;
diff --git a/frontend/src/pages/MemberReviewPage.tsx b/frontend/src/pages/MemberReviewPage.tsx
index aa4473679..9f15905fd 100644
--- a/frontend/src/pages/MemberReviewPage.tsx
+++ b/frontend/src/pages/MemberReviewPage.tsx
@@ -11,7 +11,7 @@ const MemberReviewPage = () => {
const memberReviewRef = useRef(null);
return (
-
+
@@ -20,13 +20,15 @@ const MemberReviewPage = () => {
-
+
+
);
};
export default MemberReviewPage;
-const MebmberReviewPageContainer = styled.div`
+const MemberReviewPageContainer = styled.div`
height: 100%;
+ padding: 20px 20px 0;
overflow-y: auto;
`;
diff --git a/frontend/src/pages/RecipeDetailPage.tsx b/frontend/src/pages/RecipeDetailPage.tsx
index 5ad75b4a5..cc77efb77 100644
--- a/frontend/src/pages/RecipeDetailPage.tsx
+++ b/frontend/src/pages/RecipeDetailPage.tsx
@@ -15,7 +15,7 @@ const RecipeDetailPage = () => {
const { id, images, title, content, author, products, totalPrice, favoriteCount, favorite, createdAt } = recipeDetail;
return (
- <>
+
{images.length > 0 ? (
@@ -65,12 +65,17 @@ const RecipeDetailPage = () => {
{content}
- >
+
+
);
};
export default RecipeDetailPage;
+const RecipeDetailPageContainer = styled.div`
+ padding: 20px 20px 0;
+`;
+
const RecipeImageContainer = styled.ul`
display: flex;
flex-direction: column;
diff --git a/frontend/src/types/common.ts b/frontend/src/types/common.ts
index 1d2dbb1f7..3bfcc8576 100644
--- a/frontend/src/types/common.ts
+++ b/frontend/src/types/common.ts
@@ -12,6 +12,7 @@ export const isCategoryVariant = (value: string): value is CategoryVariant => {
export interface Category {
id: number;
name: string;
+ image: string;
}
export interface Tag {