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

[FE] refactor: 홈 화면 변경 #628

Merged
merged 24 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
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
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%;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굿!

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 = () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

덜어낸거 👍👍👍

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