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

refactor: MemberImage 컴포넌트 추가 #15

Merged
merged 4 commits into from
Jan 29, 2024
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
Binary file added src/assets/defaultProfile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions src/components/Members/MemberImage/MemberImage.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { Meta, StoryObj } from '@storybook/react';

import MemberImage from './MemberImage';
import DefaultMemberImage from '../../../assets/defaultProfile.png';

const meta: Meta<typeof MemberImage> = {
title: 'members/MemberImage',
component: MemberImage,
args: {
src: 'https://github.com/woowacourse-teams/2023-fun-eat/assets/78616893/1f0fd418-131c-4cf8-b540-112d762b7c34',
alt: '펀잇님의 프로필 사진',
},
};

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

export const Default: Story = {};

export const Error: Story = {
args: {
src: DefaultMemberImage,
},
};
42 changes: 42 additions & 0 deletions src/components/Members/MemberImage/MemberImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useState } from 'react';
import type { CSSProp } from 'styled-components';
import styled from 'styled-components';

import DefaultMemberImage from '@/assets/defaultProfile.png';

interface MemberImageProps {
src: string;
alt: string;
width?: number;
height?: number;
css?: CSSProp;
}

const MemberImage = ({ src, alt, width = 45, height = 45, css }: MemberImageProps) => {
const [isError, setIsError] = useState(false);

const handleImageError = () => {
setIsError(true);
};

return (
<StyledMemberImage
src={isError ? DefaultMemberImage : src}
alt={alt}
width={width}
height={height}
css={css}
onError={handleImageError}
/>
);
Comment on lines +16 to +31
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

};

export default MemberImage;

const StyledMemberImage = styled.img`
border: 2px solid ${({ theme }) => theme.colors.primary};
border-radius: 50%;
background: ${({ theme }) => theme.backgroundColors.default};
object-fit: cover;
${({ css }) => css};
`;
20 changes: 12 additions & 8 deletions src/components/Members/MembersInfo/MembersInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Button, Heading, Link, theme } from '@fun-eat/design-system';
import { Link as RouterLink } from 'react-router-dom';
import styled from 'styled-components';

import MemberImage from '../MemberImage/MemberImage';

import { SvgIcon } from '@/components/Common';
import { PATH } from '@/constants/path';
import { useLogoutMutation, useMemberQuery } from '@/hooks/queries/members';
Expand All @@ -23,7 +25,16 @@ const MembersInfo = () => {
return (
<MembersInfoContainer>
<MemberInfoWrapper>
<MembersImage src={profileImage} width={45} height={45} alt={`${nickname}의 프로필`} />
<MemberImage
src={profileImage}
width={45}
height={45}
alt={`${nickname}의 프로필`}
css={{
marginRight: `16px`,
objectFit: `cover`,
}}
/>
<Heading size="xl" weight="bold">
{nickname} 님
</Heading>
Expand Down Expand Up @@ -55,10 +66,3 @@ const MemberModifyLink = styled(Link)`
margin-left: 5px;
transform: translateY(1px);
`;

const MembersImage = styled.img`
margin-right: 16px;
border: 2px solid ${({ theme }) => theme.colors.primary};
border-radius: 50%;
object-fit: cover;
`;
1 change: 1 addition & 0 deletions src/components/Members/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export { default as MemberReviewList } from './MemberReviewList/MemberReviewList
export { default as MemberRecipeList } from './MemberRecipeList/MemberRecipeList';
export { default as MemberModifyInput } from './MemberModifyInput/MemberModifyInput';
export { default as MemberReviewItem } from './MemberReviewItem/MemberReviewItem';
export { default as MemberImage } from './MemberImage/MemberImage';
9 changes: 2 additions & 7 deletions src/components/Rank/RecipeRankingItem/RecipeRankingItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import styled from 'styled-components';

import RecipePreviewImage from '@/assets/plate.svg';
import { SvgIcon } from '@/components/Common';
import { MemberImage } from '@/components/Members';
import type { RecipeRanking } from '@/types/ranking';
import { getRelativeDate } from '@/utils/date';

Expand Down Expand Up @@ -59,7 +60,7 @@ const RecipeRankingItem = ({ rank, recipe }: RecipeRankingItemProps) => {
</TitleFavoriteWrapper>
</RankingRecipeWrapper>
<AuthorWrapper>
<AuthorImage src={profileImage} alt={`${nickname} 님의 프로필`} width={40} height={40} />
<MemberImage src={profileImage} alt={`${nickname} 님의 프로필`} width={40} height={40} />
<Text size="sm" color={theme.textColors.sub}>
{nickname} 님
</Text>
Expand Down Expand Up @@ -114,9 +115,3 @@ const AuthorWrapper = styled.div`
align-items: center;
height: 100%;
`;

const AuthorImage = styled.img`
border: 2px solid ${({ theme }) => theme.colors.primary};
border-radius: 50%;
object-fit: cover;
`;
8 changes: 2 additions & 6 deletions src/components/Recipe/CommentItem/CommentItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Divider, Spacing, Text, useTheme } from '@fun-eat/design-system';
import styled from 'styled-components';

import { MemberImage } from '@/components/Members';
import type { Comment } from '@/types/recipe';
import { getFormattedDate } from '@/utils/date';

Expand All @@ -15,7 +16,7 @@ const CommentItem = ({ recipeComment }: CommentItemProps) => {
return (
<>
<AuthorWrapper>
<AuthorProfileImage src={author.profileImage} alt={`${author.nickname}님의 프로필`} width={32} height={32} />
<MemberImage src={author.profileImage} alt={`${author.nickname}님의 프로필`} width={32} height={32} />
<div>
<Text size="xs" color={theme.textColors.info}>
{author.nickname} 님
Expand All @@ -40,11 +41,6 @@ const AuthorWrapper = styled.div`
align-items: center;
`;

const AuthorProfileImage = styled.img`
border: 1px solid ${({ theme }) => theme.colors.primary};
border-radius: 50%;
`;

const CommentContent = styled(Text)`
margin: 16px 0;
`;
22 changes: 10 additions & 12 deletions src/components/Recipe/RecipeItem/RecipeItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import styled from 'styled-components';

import PreviewImage from '@/assets/plate.svg';
import { SvgIcon } from '@/components/Common';
import { MemberImage } from '@/components/Members';
import type { MemberRecipe, Recipe } from '@/types/recipe';
import { getFormattedDate } from '@/utils/date';

Expand All @@ -30,7 +31,15 @@ const RecipeItem = ({ recipe, isMemberPage = false }: RecipeItemProps) => {
) : (
<PreviewImage width={160} height={160} />
)}
{author && <ProfileImage src={author.profileImage} alt={`${author.nickname}의 프로필`} />}
{author && (
<MemberImage
src={author.profileImage}
alt={`${author.nickname}의 프로필`}
width={60}
height={60}
css={{ position: `absolute`, bottom: `-20px`, right: `16px` }}
/>
)}
</ImageWrapper>
)}
<RecipeInfoWrapper>
Expand Down Expand Up @@ -76,17 +85,6 @@ const RecipeImage = styled.img`
object-fit: cover;
`;

const ProfileImage = styled.img`
position: absolute;
bottom: -20px;
right: 16px;
width: 60px;
height: 60px;
border: 2px solid ${({ theme }) => theme.colors.primary};
border-radius: 50%;
background-color: ${({ theme }) => theme.backgroundColors.default};
`;

const RecipeInfoWrapper = styled.div`
position: relative;
display: flex;
Expand Down
9 changes: 2 additions & 7 deletions src/components/Review/BestReviewItem/BestReviewItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Spacing, Text, useTheme } from '@fun-eat/design-system';
import styled from 'styled-components';

import { SvgIcon } from '@/components/Common';
import { MemberImage } from '@/components/Members';
import { useBestReviewQuery } from '@/hooks/queries/rank';

interface BestReviewItemProps {
Expand Down Expand Up @@ -29,7 +30,7 @@ const BestReviewItem = ({ productId }: BestReviewItemProps) => {
<BestReviewItemContainer>
<ReviewRateFavoriteWrapper>
<ReviewerInfoWrapper>
<ReviewerImage src={profileImage} width={32} height={32} alt={`${userName}의 프로필`} />
<MemberImage src={profileImage} width={32} height={32} alt={`${userName}의 프로필`} />
<div>
<Text size="sm" weight="bold">
{userName} 님
Expand Down Expand Up @@ -82,12 +83,6 @@ const ReviewerInfoWrapper = styled.div`
column-gap: 10px;
`;

const ReviewerImage = styled.img`
border: 2px solid ${({ theme }) => theme.colors.primary};
border-radius: 50%;
object-fit: cover;
`;

const FavoriteWrapper = styled.div`
display: flex;
gap: 8px;
Expand Down
15 changes: 8 additions & 7 deletions src/components/Review/ReviewItem/ReviewItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import styled from 'styled-components';
import ReviewFavoriteButton from '../ReviewFavoriteButton/ReviewFavoriteButton';

import { SvgIcon, TagList } from '@/components/Common';
import { MemberImage } from '@/components/Members';
import type { Review } from '@/types/review';
import { getRelativeDate } from '@/utils/date';

Expand All @@ -23,7 +24,13 @@ const ReviewItem = ({ productId, review }: ReviewItemProps) => {
<ReviewItemContainer>
<ReviewerWrapper>
<ReviewerInfoWrapper>
<ReviewerImage src={profileImage} width={40} height={40} alt={`${userName}의 프로필`} />
<MemberImage
src={profileImage}
width={40}
height={40}
alt={`${userName}의 프로필`}
css={{ objectFit: `cover` }}
/>
<div>
<Text weight="bold">{userName}</Text>
<RatingIconWrapper>
Expand Down Expand Up @@ -80,12 +87,6 @@ const RebuyBadge = styled(Badge)`
font-weight: ${({ theme }) => theme.fontWeights.bold};
`;

const ReviewerImage = styled.img`
border: 2px solid ${({ theme }) => theme.colors.primary};
border-radius: 50%;
object-fit: cover;
`;

const RatingIconWrapper = styled.div`
display: flex;
align-items: center;
Expand Down
8 changes: 2 additions & 6 deletions src/pages/RecipeDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import styled from 'styled-components';

import RecipePreviewImage from '@/assets/plate.svg';
import { ErrorBoundary, ErrorComponent, Loading, SectionTitle } from '@/components/Common';
import { MemberImage } from '@/components/Members';
import { CommentForm, CommentList, RecipeFavoriteButton } from '@/components/Recipe';
import { useRecipeDetailQuery } from '@/hooks/queries/recipe';
import { getFormattedDate } from '@/utils/date';
Expand Down Expand Up @@ -40,7 +41,7 @@ export const RecipeDetailPage = () => {
<Spacing size={24} />
<AuthorFavoriteWrapper>
<AuthorWrapper>
<AuthorProfileImage src={author.profileImage} alt={`${author.nickname}님의 프로필`} width={45} height={45} />
<MemberImage src={author.profileImage} alt={`${author.nickname}님의 프로필`} width={45} height={45} />
<div>
<Text color={theme.textColors.info}>{author.nickname} 님</Text>
<Text color={theme.textColors.info}> {getFormattedDate(createdAt)}</Text>
Expand Down Expand Up @@ -124,11 +125,6 @@ const AuthorWrapper = styled.div`
align-items: center;
`;

const AuthorProfileImage = styled.img`
border: 1px solid ${({ theme }) => theme.colors.primary};
border-radius: 50%;
`;

const RecipeUsedProductsWrapper = styled.div`
padding: 20px;
border-radius: 8px;
Expand Down
15 changes: 8 additions & 7 deletions src/pages/ReviewDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useParams } from 'react-router-dom';
import styled from 'styled-components';

import { SectionTitle, SvgIcon, TagList } from '@/components/Common';
import { MemberImage } from '@/components/Members';
import { PATH } from '@/constants/path';
import { useReviewDetailQuery } from '@/hooks/queries/review';
import { getRelativeDate } from '@/utils/date';
Expand Down Expand Up @@ -35,7 +36,13 @@ export const ReviewDetailPage = () => {
<ReviewItemContainer>
<ReviewerWrapper>
<ReviewerInfoWrapper>
<ReviewerImage src={profileImage} width={40} height={40} alt={`${userName}의 프로필`} />
<MemberImage
src={profileImage}
width={40}
height={40}
alt={`${userName}의 프로필`}
css={{ objectFit: `cover` }}
/>
<div>
<Text weight="bold">{userName}</Text>
<RatingIconWrapper>
Expand Down Expand Up @@ -100,12 +107,6 @@ const RebuyBadge = styled(Badge)`
font-weight: ${({ theme }) => theme.fontWeights.bold};
`;

const ReviewerImage = styled.img`
border: 2px solid ${({ theme }) => theme.colors.primary};
border-radius: 50%;
object-fit: cover;
`;

const RatingIconWrapper = styled.div`
display: flex;
align-items: center;
Expand Down
Loading