Skip to content

Commit

Permalink
v1.2.5 (#729)
Browse files Browse the repository at this point in the history
v1.2.5
  • Loading branch information
Leejin-Yang authored Oct 6, 2023
2 parents 3facdfa + 062ca02 commit 120e4f9
Show file tree
Hide file tree
Showing 21 changed files with 179 additions and 37 deletions.
4 changes: 2 additions & 2 deletions backend/src/main/java/com/funeat/common/s3/S3Uploader.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
@Profile("!test")
public class S3Uploader implements ImageUploader {

private static final List<String> INCLUDE_EXTENSIONS = List.of("image/jpeg", "image/png");
private static final List<String> INCLUDE_EXTENSIONS = List.of("image/jpeg", "image/png", "image/webp");

@Value("${cloud.aws.s3.bucket}")
private String bucket;
Expand Down Expand Up @@ -55,7 +55,7 @@ public String upload(final MultipartFile image) {

private void validateExtension(final MultipartFile image) {
final String contentType = image.getContentType();
if (!INCLUDE_EXTENSIONS.contains(contentType)){
if (!INCLUDE_EXTENSIONS.contains(contentType)) {
throw new NotAllowedFileExtensionException(IMAGE_EXTENSION_ERROR_CODE, contentType);
}
}
Expand Down
4 changes: 1 addition & 3 deletions frontend/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>펀잇</title>
<meta name="description" content="궁금해? 맛있을걸? 먹어봐 🥄" />
<meta name="description" content="펀잇은 모든 편의점 음식, 리뷰, 꿀조합을 한눈에 확인할 수 있는 서비스입니다." />
<meta property="og:title" content="펀잇" />
<meta property="og:description" content="궁금해? 맛있을걸? 먹어봐 🥄" />
<meta property="og:url" content="https://funeat.site" />
<meta property="og:site_name" content="펀잇" />
<meta property="og:type" content="website" />
<meta property="og:image" content="/assets/og-image.png" />
<meta property="og:image:alt" content="펀잇" />
<meta property="og:type" content="website" />
Expand All @@ -25,7 +24,6 @@
href="https://cdn.jsdelivr.net/gh/orioncactus/[email protected]/dist/web/variable/pretendardvariable-dynamic-subset.css"
onload="this.onload=null; this.rel='stylesheet'"
/>
<title>펀잇</title>
</head>
<body>
<div id="root"></div>
Expand Down
9 changes: 9 additions & 0 deletions frontend/public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
User-agent: *
Disallow: /404
Allow: /

# Host
Host: https://funeat.site/

# Sitemaps
Sitemap: https://funeat.site/sitemap.xml
23 changes: 23 additions & 0 deletions frontend/public/sitemap.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>https://funeat.site</loc>
<lastmod>2023-09-25T05:39:39+00:00</lastmod>
</url>
<url>
<loc>https://funeat.site/products/food</loc>
<lastmod>2023-09-25T05:39:39+00:00</lastmod>
</url>
<url>
<loc>https://funeat.site/products/store</loc>
<lastmod>2023-09-25T05:39:39+00:00</lastmod>
</url>
<url>
<loc>https://funeat.site/recipes</loc>
<lastmod>2023-09-25T05:39:39+00:00</lastmod>
</url>
</urlset>
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,33 @@ import styled from 'styled-components';
import CategoryItem from '../CategoryItem/CategoryItem';

import { CATEGORY_TYPE } from '@/constants';
import { useGA } from '@/hooks/common';
import { useCategoryFoodQuery } from '@/hooks/queries/product';

const category = CATEGORY_TYPE.FOOD;

const CategoryFoodList = () => {
const { data: categories } = useCategoryFoodQuery(category);
const { gaEvent } = useGA();

const handleHomeCategoryLinkClick = (categoryName: string) => {
gaEvent({
category: 'link',
action: `${categoryName} 카테고리 링크 클릭`,
label: '카테고리',
});
};

return (
<div>
<CategoryFoodListWrapper>
{categories.map((menu) => (
<Link key={menu.id} as={RouterLink} to={`products/food?category=${menu.id}`}>
<Link
key={menu.id}
as={RouterLink}
to={`products/food?category=${menu.id}`}
onClick={() => handleHomeCategoryLinkClick(menu.name)}
>
<CategoryItem name={menu.name} image={menu.image} />
</Link>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import { useLocation } from 'react-router-dom';
import styled from 'styled-components';

import { CATEGORY_TYPE } from '@/constants';
import { useGA } from '@/hooks/common';
import { useCategoryActionContext, useCategoryValueContext } from '@/hooks/context';
import { useCategoryFoodQuery } from '@/hooks/queries/product/useCategoryQuery';
import { getTargetCategoryName } from '@/utils/category';

const category = CATEGORY_TYPE.FOOD;

Expand All @@ -20,12 +22,23 @@ const CategoryFoodTab = () => {
const queryParams = new URLSearchParams(location.search);
const categoryIdFromURL = queryParams.get('category');

const { gaEvent } = useGA();

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

const handleCategoryButtonClick = (menuId: number) => {
selectCategory(category, menuId);
gaEvent({
category: 'button',
action: `${getTargetCategoryName(categories, menuId)} 카테고리 버튼 클릭`,
label: '카테고리',
});
};

return (
<CategoryMenuContainer>
{categories.map((menu) => {
Expand All @@ -40,7 +53,7 @@ const CategoryFoodTab = () => {
weight="bold"
variant={isSelected ? 'filled' : 'outlined'}
isSelected={isSelected}
onClick={() => selectCategory(category, menu.id)}
onClick={() => handleCategoryButtonClick(menu.id)}
aria-pressed={isSelected}
>
{menu.name}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,33 @@ import styled from 'styled-components';
import CategoryItem from '../CategoryItem/CategoryItem';

import { CATEGORY_TYPE } from '@/constants';
import { useGA } from '@/hooks/common';
import { useCategoryStoreQuery } from '@/hooks/queries/product';

const category = CATEGORY_TYPE.STORE;

const CategoryStoreList = () => {
const { data: categories } = useCategoryStoreQuery(category);
const { gaEvent } = useGA();

const handleHomeCategoryLinkClick = (categoryName: string) => {
gaEvent({
category: 'link',
action: `${categoryName} 카테고리 링크 클릭`,
label: '카테고리',
});
};

return (
<div>
<CategoryStoreListWrapper>
{categories.map((menu) => (
<Link key={menu.id} as={RouterLink} to={`products/store?category=${menu.id}`}>
<Link
key={menu.id}
as={RouterLink}
to={`products/store?category=${menu.id}`}
onClick={() => handleHomeCategoryLinkClick(menu.name)}
>
<CategoryItem name={menu.name} image={menu.image} />
</Link>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import { useLocation } from 'react-router-dom';
import styled from 'styled-components';

import { CATEGORY_TYPE } from '@/constants';
import { useGA } from '@/hooks/common';
import { useCategoryActionContext, useCategoryValueContext } from '@/hooks/context';
import { useCategoryStoreQuery } from '@/hooks/queries/product/useCategoryQuery';
import { getTargetCategoryName } from '@/utils/category';

const category = CATEGORY_TYPE.STORE;

Expand All @@ -20,12 +22,23 @@ const CategoryStoreTab = () => {
const queryParams = new URLSearchParams(location.search);
const categoryIdFromURL = queryParams.get('category');

const { gaEvent } = useGA();

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

const handleCategoryButtonClick = (menuId: number) => {
selectCategory(category, menuId);
gaEvent({
category: 'button',
action: `${getTargetCategoryName(categories, menuId)} 카테고리 버튼 클릭`,
label: '카테고리',
});
};

return (
<CategoryMenuContainer>
{categories.map((menu) => {
Expand All @@ -40,7 +53,7 @@ const CategoryStoreTab = () => {
weight="bold"
variant={isSelected ? 'filled' : 'outlined'}
isSelected={isSelected}
onClick={() => selectCategory(category, menu.id)}
onClick={() => handleCategoryButtonClick(menu.id)}
aria-pressed={isSelected}
>
{menu.name}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Link as RouterLink } from 'react-router-dom';

import { ProductOverviewItem } from '@/components/Product';
import { PATH } from '@/constants/path';
import { useGA } from '@/hooks/common';
import { useProductRankingQuery } from '@/hooks/queries/rank';
import displaySlice from '@/utils/displaySlice';

Expand All @@ -12,13 +13,22 @@ interface ProductRankingListProps {

const ProductRankingList = ({ isHomePage = false }: ProductRankingListProps) => {
const { data: productRankings } = useProductRankingQuery();
const { gaEvent } = useGA();
const productsToDisplay = displaySlice(isHomePage, productRankings.products, 3);

const handleProductRankingLinkClick = () => {
gaEvent({ category: 'link', action: '상품 랭킹 링크 클릭', label: '랭킹' });
};

return (
<ul>
{productsToDisplay.map(({ id, name, image, categoryType }, index) => (
<li key={id}>
<Link as={RouterLink} to={`${PATH.PRODUCT_LIST}/${categoryType}/${id}`}>
<Link
as={RouterLink}
to={`${PATH.PRODUCT_LIST}/${categoryType}/${id}`}
onClick={handleProductRankingLinkClick}
>
<ProductOverviewItem rank={index + 1} name={name} image={image} />
</Link>
<Spacing size={16} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,23 @@ import RecipeRankingItem from '../RecipeRankingItem/RecipeRankingItem';

import { Carousel } from '@/components/Common';
import { PATH } from '@/constants/path';
import { useGA } from '@/hooks/common';
import { useRecipeRankingQuery } from '@/hooks/queries/rank';

const RecipeRankingList = () => {
const { data: recipeResponse } = useRecipeRankingQuery();
const { gaEvent } = useGA();

if (recipeResponse.recipes.length === 0) return <Text size="lg">아직 랭킹이 없어요!</Text>;

const handleRecipeRankingLinkClick = () => {
gaEvent({ category: 'link', action: '꿀조합 랭킹 링크 클릭', label: '랭킹' });
};

const carouselList = recipeResponse.recipes.map((recipe, index) => ({
id: index,
children: (
<Link as={RouterLink} to={`${PATH.RECIPE}/${recipe.id}`}>
<Link as={RouterLink} to={`${PATH.RECIPE}/${recipe.id}`} onClick={handleRecipeRankingLinkClick}>
<RecipeRankingItem rank={index + 1} recipe={recipe} />
</Link>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import styled from 'styled-components';
import ReviewRankingItem from '../ReviewRankingItem/ReviewRankingItem';

import { PATH } from '@/constants/path';
import { useGA } from '@/hooks/common';
import { useReviewRankingQuery } from '@/hooks/queries/rank';
import useDisplaySlice from '@/utils/displaySlice';

Expand All @@ -14,15 +15,21 @@ interface ReviewRankingListProps {

const ReviewRankingList = ({ isHomePage = false }: ReviewRankingListProps) => {
const { data: reviewRankings } = useReviewRankingQuery();
const { gaEvent } = useGA();
const reviewsToDisplay = useDisplaySlice(isHomePage, reviewRankings.reviews);

const handleReviewRankingLinkClick = () => {
gaEvent({ category: 'link', action: '리뷰 랭킹 링크 클릭', label: '랭킹' });
};

return (
<ReviewRankingListContainer>
{reviewsToDisplay.map((reviewRanking) => (
<li key={reviewRanking.reviewId}>
<Link
as={RouterLink}
to={`${PATH.PRODUCT_LIST}/${reviewRanking.categoryType}/${reviewRanking.productId}`}
onClick={handleReviewRankingLinkClick}
block
>
<ReviewRankingItem reviewRanking={reviewRanking} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ const RecipeRegisterForm = ({ closeRecipeDialog }: RecipeRegisterFormProps) => {
</Text>
<Spacing size={10} />
<FormButton customWidth="100%" customHeight="60px" size="xl" weight="bold" disabled={!isValid || isLoading}>
레시피 등록하기
꿀조합 등록하기
</FormButton>
<Spacing size={50} />
</form>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/hooks/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export { default as useTimeout } from './useTimeout';
export { default as useRouteChangeTracker } from './useRouteChangeTracker';
export { default as useTabMenu } from './useTabMenu';
export { default as useScrollRestoration } from './useScrollRestoration';
export { default as useGA } from './useGA';
20 changes: 20 additions & 0 deletions frontend/src/hooks/common/useGA.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useCallback } from 'react';
import ReactGA from 'react-ga4';

interface GAEventProps {
category: string;
action: string;
label?: string;
}

const useGA = () => {
// TODO: navigate event tracking

const gaEvent = useCallback((eventProps: GAEventProps) => {
ReactGA.event(eventProps);
}, []);

return { gaEvent };
};

export default useGA;
5 changes: 5 additions & 0 deletions frontend/src/hooks/search/useSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { ChangeEventHandler, FormEventHandler, MouseEventHandler } from 're
import { useRef, useState } from 'react';
import { useSearchParams } from 'react-router-dom';

import { useGA } from '../common';

const useSearch = () => {
const inputRef = useRef<HTMLInputElement>(null);

Expand All @@ -12,6 +14,8 @@ const useSearch = () => {
const [isSubmitted, setIsSubmitted] = useState(!!currentSearchQuery);
const [isAutocompleteOpen, setIsAutocompleteOpen] = useState(searchQuery.length > 0);

const { gaEvent } = useGA();

const focusInput = () => {
if (inputRef.current) {
inputRef.current.focus();
Expand All @@ -26,6 +30,7 @@ const useSearch = () => {

const handleSearch: FormEventHandler<HTMLFormElement> = (event) => {
event.preventDefault();
gaEvent({ category: 'submit', action: '검색 페이지에서 검색', label: '검색' });

const trimmedSearchQuery = searchQuery.trim();

Expand Down
6 changes: 2 additions & 4 deletions frontend/src/pages/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Heading, Link, Spacing } from '@fun-eat/design-system';
import { Heading, Spacing } from '@fun-eat/design-system';
import { useQueryErrorResetBoundary } from '@tanstack/react-query';
import { Suspense } from 'react';
import styled from 'styled-components';
Expand All @@ -20,9 +20,7 @@ export const HomePage = () => {
return (
<>
<section>
<Link href="https://www.instagram.com/p/CxmlqAQSK-w/?igshid=MzRlODBiNWFlZA==" isExternal>
<Banner src={`${IMAGE_URL}banner.png`} width={600} height={360} alt="이벤트 배너" />
</Link>
<Banner src={`${IMAGE_URL}banner.png`} width={600} height={360} alt="이벤트 배너" />
</section>
<Spacing size={40} />
<SectionWrapper>
Expand Down
Loading

0 comments on commit 120e4f9

Please sign in to comment.