Skip to content

Commit

Permalink
[FE] refactor: 홈 화면 변경 (#628)
Browse files Browse the repository at this point in the history
* chore: 파일명 변경

* chore: 카테고리 이미지 추가

* feat: category item 구현

* chore: 이미지 s3로 이동

* refactor: 카테고리 아이템 수정

* refactor: home 분기 삭제

* refactor: button으로 변경

* feat: 카테고리 리스트 구현

* refactor: home 화면 category 디자인 수정

* refactor: key 이름 변경

* feat: 배너 추가

* refactor: 배너 링크 추가

* refactor: 간격 조절

* chore: 이미지 삭제

* chore: 배너 경로 TODO 작성

* refactor: 캐러셀 디자인 수정

* refactor: 폰트 단위 수정

* chore: tab -> menu로 변경

* refactor: 리뷰 반영

* refactor: 카테고리 json 수정

* refactor: 카테고리 클릭 시 이동하도록 수정

* refactor: 카테고리 이동 구현
  • Loading branch information
hae-on authored Sep 15, 2023
1 parent 5ae7ec0 commit 9b413fa
Show file tree
Hide file tree
Showing 16 changed files with 227 additions and 81 deletions.
4 changes: 3 additions & 1 deletion frontend/src/components/Common/Carousel/Carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ export default Carousel;

const CarouselContainer = styled.div`
display: flex;
width: ${CAROUSEL_WIDTH}px;
width: 100%;
border: 1px solid ${({ theme }) => theme.colors.gray2};
border-radius: 10px;
overflow: hidden;
`;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Meta, StoryObj } from '@storybook/react';

import CategoryItem from './CategoryItem';

const meta: Meta<typeof CategoryItem> = {
title: 'common/CategoryItem',
component: CategoryItem,
args: {
name: '즉석 식품',
image: 'https://tqklhszfkvzk6518638.cdn.ntruss.com/product/8801771029052.jpg',
},
};

export default meta;
type Story = StoryObj<typeof CategoryItem>;

export const Default: Story = {};
48 changes: 48 additions & 0 deletions frontend/src/components/Common/CategoryItem/CategoryItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Button } from '@fun-eat/design-system';
import styled from 'styled-components';

interface CategoryItemProps {
name: string;
image: string;
}

const CategoryItem = ({ name, image }: CategoryItemProps) => {
return (
<CategoryItemContainer variant="transparent">
<ImageWrapper>
<img src={image} width={60} height={60} alt={name} />
</ImageWrapper>
<CategoryName>{name}</CategoryName>
</CategoryItemContainer>
);
};

export default CategoryItem;

const CategoryItemContainer = styled(Button)`
width: 60px;
height: 100px;
text-align: center;
`;

const ImageWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
width: 60px;
height: 60px;
border-radius: 10px;
background: ${({ theme }) => theme.colors.white};
img {
width: 100%;
height: auto;
object-fit: cover;
}
`;

const CategoryName = styled.p`
margin-top: 10px;
font-weight: 600;
font-size: 0.8rem;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Meta, StoryObj } from '@storybook/react';

import CategoryList from './CategoryList';

const meta: Meta<typeof CategoryList> = {
title: 'common/CategoryList',
component: CategoryList,
};

export default meta;
type Story = StoryObj<typeof CategoryList>;

export const Default: Story = {};
68 changes: 68 additions & 0 deletions frontend/src/components/Common/CategoryList/CategoryList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Link } from '@fun-eat/design-system';
import { Link as RouterLink } from 'react-router-dom';
import styled from 'styled-components';

import CategoryItem from '../CategoryItem/CategoryItem';

import { MENU_IMAGES, MENU_NAME, STORE_IMAGES, STORE_NAMES } from '@/constants';

const MENU_LENGTH = 5;
const STORE_LENGTH = 4;

const menuList = Array.from({ length: MENU_LENGTH }, (_, index) => ({
name: MENU_NAME[index],
image: MENU_IMAGES[index],
}));

const storeList = Array.from({ length: STORE_LENGTH }, (_, index) => ({
name: STORE_NAMES[index],
image: STORE_IMAGES[index],
}));

const CategoryList = () => {
return (
<CategoryListContainer>
<MenuListWrapper>
{menuList.map((menu, index) => (
<Link key={`menuItem-${index}`} as={RouterLink} to={`products/food?category=${index + 1}`}>
<CategoryItem name={menu.name} image={menu.image} />
</Link>
))}
</MenuListWrapper>
<StoreListWrapper>
{storeList.map((menu, index) => (
<Link key={`menuItem-${index}`} as={RouterLink} to={`products/store?category=${index + 6}`}>
<CategoryItem key={`storeItem-${index}`} name={menu.name} image={menu.image} />
</Link>
))}
</StoreListWrapper>
</CategoryListContainer>
);
};

export default CategoryList;

const CategoryListContainer = styled.div`
overflow-x: auto;
overflow-y: hidden;
@media screen and (min-width: 500px) {
display: flex;
flex-direction: column;
align-items: center;
}
&::-webkit-scrollbar {
display: none;
}
`;

const MenuListWrapper = styled.div`
display: flex;
gap: 20px;
`;

const StoreListWrapper = styled.div`
display: flex;
gap: 20px;
`;
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { Meta, StoryObj } from '@storybook/react';

import CategoryMenu from './CategoryMenu';
import CategoryTab from './CategoryTab';

const meta: Meta<typeof CategoryMenu> = {
title: 'common/CategoryMenu',
component: CategoryMenu,
const meta: Meta<typeof CategoryTab> = {
title: 'common/CategoryTab',
component: CategoryTab,
};

export default meta;
type Story = StoryObj<typeof CategoryMenu>;
type Story = StoryObj<typeof CategoryTab>;

export const FoodCategory: Story = {
args: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Button, theme } from '@fun-eat/design-system';
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import type { CSSProp } from 'styled-components';
import styled from 'styled-components';

Expand All @@ -10,12 +12,23 @@ interface CategoryMenuProps {
menuVariant: CategoryVariant;
}

const CategoryMenu = ({ menuVariant }: CategoryMenuProps) => {
const CategoryTab = ({ menuVariant }: CategoryMenuProps) => {
const { data: categories } = useCategoryQuery(menuVariant);

const { categoryIds } = useCategoryValueContext();
const { selectCategory } = useCategoryActionContext();
const currentCategoryId = categoryIds[menuVariant];

const location = useLocation();
const queryParams = new URLSearchParams(location.search);
const categoryIdFromURL = queryParams.get('category');

useEffect(() => {
if (categoryIdFromURL) {
selectCategory(menuVariant, parseInt(categoryIdFromURL));
}
}, [location]);

return (
<CategoryMenuContainer>
{categories.map((menu) => {
Expand Down Expand Up @@ -43,7 +56,7 @@ const CategoryMenu = ({ menuVariant }: CategoryMenuProps) => {
);
};

export default CategoryMenu;
export default CategoryTab;

type CategoryMenuStyleProps = Pick<CategoryMenuProps, 'menuVariant'>;

Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/Common/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { default as CategoryMenu } from './CategoryMenu/CategoryMenu';
export { default as CategoryTab } from './CategoryTab/CategoryTab';
export { default as Header } from './Header/Header';
export { default as NavigationBar } from './NavigationBar/NavigationBar';
export { default as SortButton } from './SortButton/SortButton';
Expand All @@ -19,3 +19,5 @@ export { default as MoreButton } from './MoreButton/MoreButton';
export { default as NavigableSectionTitle } from './NavigableSectionTitle/NavigableSectionTitle';
export { default as Carousel } from './Carousel/Carousel';
export { default as RegisterButton } from './RegisterButton/RegisterButton';
export { default as CategoryItem } from './CategoryItem/CategoryItem';
export { default as CategoryList } from './CategoryList/CategoryList';
10 changes: 2 additions & 8 deletions frontend/src/components/Product/PBProductList/PBProductList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,17 @@ import { MoreButton } from '@/components/Common';
import { PATH } from '@/constants/path';
import { useCategoryValueContext } from '@/hooks/context';
import { useInfiniteProductsQuery } from '@/hooks/queries/product';
import displaySlice from '@/utils/displaySlice';

interface PBProductListProps {
isHomePage?: boolean;
}

const PBProductList = ({ isHomePage }: PBProductListProps) => {
const PBProductList = () => {
const { categoryIds } = useCategoryValueContext();

const { data: pbProductListResponse } = useInfiniteProductsQuery(categoryIds.store);
const pbProducts = pbProductListResponse.pages.flatMap((page) => page.products);
const pbProductsToDisplay = displaySlice(isHomePage, pbProducts, 10);

return (
<>
<PBProductListContainer>
{pbProductsToDisplay.map((pbProduct) => (
{pbProducts.map((pbProduct) => (
<li key={pbProduct.id}>
<Link as={RouterLink} to={`${PATH.PRODUCT_LIST}/store/${pbProduct.id}`}>
<PBProductItem pbProduct={pbProduct} />
Expand Down
7 changes: 2 additions & 5 deletions frontend/src/components/Product/ProductList/ProductList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@ import { useIntersectionObserver, useScrollRestoration } from '@/hooks/common';
import { useCategoryValueContext } from '@/hooks/context';
import { useInfiniteProductsQuery } from '@/hooks/queries/product';
import type { CategoryVariant, SortOption } from '@/types/common';
import displaySlice from '@/utils/displaySlice';

interface ProductListProps {
category: CategoryVariant;
isHomePage?: boolean;
selectedOption?: SortOption;
}

const ProductList = ({ category, isHomePage, selectedOption }: ProductListProps) => {
const ProductList = ({ category, selectedOption }: ProductListProps) => {
const scrollRef = useRef<HTMLDivElement>(null);
const productListRef = useRef<HTMLDivElement>(null);

Expand All @@ -34,12 +32,11 @@ const ProductList = ({ category, isHomePage, selectedOption }: ProductListProps)
useScrollRestoration(categoryIds[category], productListRef);

const productList = data.pages.flatMap((page) => page.products);
const productsToDisplay = displaySlice(isHomePage, productList);

return (
<ProductListContainer ref={productListRef}>
<ProductListWrapper>
{productsToDisplay.map((product) => (
{productList.map((product) => (
<li key={product.id}>
<Link as={RouterLink} to={`${PATH.PRODUCT_LIST}/${category}/${product.id}`}>
<ProductItem product={product} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@ const RecipeRankingItem = ({ rank, recipe }: RecipeRankingItemProps) => {
<Spacing direction="horizontal" size={12} />
<RecipeRankingWrapper>
<RankingRecipeWrapper>
<Text weight="bold">{rank}</Text>
<Spacing direction="horizontal" size={12} />
{image !== null ? (
<RecipeImage src={image} alt={`${rank}위 꿀조합`} width={60} height={60} />
) : (
<RecipePreviewImage width={60} height={60} />
)}
<Spacing direction="horizontal" size={12} />
<Spacing direction="horizontal" size={20} />
<TitleFavoriteWrapper>
<Text weight="bold">{title}</Text>
<FavoriteWrapper>
Expand All @@ -57,16 +56,15 @@ export default RecipeRankingItem;

const RecipeRankingItemContainer = styled.div`
width: calc(100% - 50px);
height: 72px;
max-width: 560px;
margin: 12px 0;
padding: 0 24px;
padding: 0 5px;
`;

const RecipeRankingWrapper = styled.div`
display: flex;
justify-content: space-between;
width: 100%;
width: 95%;
`;

const RankingRecipeWrapper = styled.div`
Expand Down
22 changes: 22 additions & 0 deletions frontend/src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,25 @@ export const CATEGORY_TYPE = {
export const IMAGE_MAX_SIZE = 5 * 1024 * 1024;

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`,
];
11 changes: 5 additions & 6 deletions frontend/src/mocks/data/foodCategory.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
[
{ "id": 1, "name": "즉석조리" },
{ "id": 2, "name": "과자" },
{ "id": 3, "name": "간편식사" },
{ "id": 4, "name": "아이스크림" },
{ "id": 5, "name": "식품" },
{ "id": 6, "name": "음료" }
{ "id": 1, "name": "간편식사" },
{ "id": 2, "name": "과자류" },
{ "id": 3, "name": "아이스크림" },
{ "id": 4, "name": "식품" },
{ "id": 5, "name": "음료" }
]
7 changes: 4 additions & 3 deletions frontend/src/mocks/data/storeCategory.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[
{ "id": 7, "name": "CU" },
{ "id": 8, "name": "GS25" },
{ "id": 9, "name": "이마트24" }
{ "id": 6, "name": "CU" },
{ "id": 7, "name": "GS25" },
{ "id": 8, "name": "이마트24" },
{ "id": 9, "name": "세븐일레븐" }
]
Loading

0 comments on commit 9b413fa

Please sign in to comment.