Skip to content

Commit

Permalink
feat: 마이페이지 구현 (#95)
Browse files Browse the repository at this point in the history
* refactor: memberImage 컴포넌트 마이그레이션 및 props 수정

* refactor: memberInfo 컴포넌트 마이그레이션 및 디자인 수정

* feat: postCounterBox 컴포넌트 구현

* refactor: memberPage 마이그레이션

* feat: memberPostPage 구현

* feat: starRating 컴포넌트 구현

* refactor: memberReviewItem 컴포넌트 마이그레이션 및 수정

* refactor: memberReviewList 컴포넌트 디자인 수정

* refactor: 세부 디자인 수정

* refactor: memberRecipeList 디자인 수정

* refactor: 세부 레이아웃 수정

* refactor: 필요없는 css 삭제

* refactor: 화살표 svg 위치 수정

* chore: 사용하지 않는 페이지 삭제

* fix: webpack vanilla error hash 값 추가하여 해결

* refactor: review item 일부 컴포넌트로 분리

* feat: 작성한 꿀조합/리뷰 클릭에 따른 페이지 이동 구현

* chore: 사용하지 않는 css 삭제

* refactor: member에 recipeCount, reviewCount 추가

* refactor: 세부 디자인 반영

* refactor: camera2 아이콘 교체

* chore: svg 속성 카멜 케이스로 자동 변경

* fix: css 순서 오류 방지

* chore: lint 적용

* refactor: memberModifyInput 스타일 마이그레이션 및 수정

* refactor: 레이아웃 변경

* refactor: memberModifyPage 디자인 마이그레이션 및 수정

* chore: 주석  추가
  • Loading branch information
hae-on authored Apr 28, 2024
1 parent 34e246f commit 0e8de8d
Show file tree
Hide file tree
Showing 58 changed files with 906 additions and 729 deletions.
26 changes: 13 additions & 13 deletions .storybook/preview-body.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,19 @@
</clipPath>
</defs>
</symbol>
<symbol id="camera2" viewBox="0 0 14 14">
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M13.5 5a1 1 0 0 0-1-1h-2L9 2H5L3.5 4h-2a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1V5z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M7 9.75a2.25 2.25 0 1 0 0-4.5 2.25 2.25 0 0 0 0 4.5z"
/>
<symbol id="camera2" viewBox="0 0 13 12">
<g clip-path="url(#a)">
<path
fill-rule="evenodd"
d="M4.443 1.457a.429.429 0 0 1 .343-.171h3.428c.135 0 .262.063.343.171L9.714 3h1.5A1.286 1.286 0 0 1 12.5 4.286v5.143a1.286 1.286 0 0 1-1.286 1.285H1.786A1.285 1.285 0 0 1 .5 9.43V4.286A1.286 1.286 0 0 1 1.786 3h1.5l1.157-1.543zM8.61 6.61a2.11 2.11 0 1 1-4.22 0 2.11 2.11 0 0 1 4.22 0z"
clip-rule="evenodd"
/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h12v12H0z" transform="translate(.5)" />
</clipPath>
</defs>
</symbol>
<symbol id="favorite2" viewBox="0 0 14 14">
<path
Expand Down
Binary file modified 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.
1 change: 0 additions & 1 deletion src/components/Common/SectionHeader/sectionHeader.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { style } from '@vanilla-extract/css';
export const container = style({
display: 'flex',
justifyContent: 'space-between',
padding: '0 20px',
});

export const title = style({
Expand Down
17 changes: 17 additions & 0 deletions src/components/Common/StarRating/StarRating.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Meta, StoryObj } from '@storybook/react';

import StarRating from './StarRating';

const meta: Meta<typeof StarRating> = {
title: 'common/StarRating',
component: StarRating,
args: {
rating: 4.5,
createdAt: '2021-09-01T00:00:00.000Z',
},
};

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

export const Default: Story = {};
37 changes: 37 additions & 0 deletions src/components/Common/StarRating/StarRating.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { date, ratingInfo, ratingNumber, ratingWrapper } from './starRating.css';
import SvgIcon from '../Svg/SvgIcon';
import Text from '../Text/Text';

import { vars } from '@/styles/theme.css';
import { getRelativeDate } from '@/utils/date';

interface StarRatingProps {
rating: number;
createdAt: string;
}

const StarRating = ({ rating, createdAt }: StarRatingProps) => {
return (
<div className={ratingWrapper}>
<div className={ratingInfo}>
<Text as="span" size="caption3" weight="medium" className={ratingNumber}>
{rating.toFixed(1)}
</Text>
{Array.from({ length: 5 }, (_, index) => (
<SvgIcon
key={`rating-${index}`}
variant="star2"
fill={index < rating ? vars.colors.icon.fill : vars.colors.icon.light}
width={13}
height={13}
/>
))}
</div>
<Text as="span" size="caption4" color="disabled" className={date}>
{getRelativeDate(createdAt)}
</Text>
</div>
);
};

export default StarRating;
23 changes: 23 additions & 0 deletions src/components/Common/StarRating/starRating.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { vars } from '@/styles/theme.css';
import { style } from '@vanilla-extract/css';

export const ratingWrapper = style({
display: 'flex',
alignItems: 'center',
gap: 8,
});

export const ratingInfo = style({
display: 'flex',
alignItems: 'center',
gap: 4,
});

export const ratingNumber = style({
paddingTop: 4,
color: vars.colors.gray5,
});

export const date = style({
paddingTop: 2,
});
26 changes: 13 additions & 13 deletions src/components/Common/Svg/SvgSprite.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,19 @@ const SvgSprite = () => {
</clipPath>
</defs>
</symbol>
<symbol id="camera2" viewBox="0 0 14 14">
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M13.5 5a1 1 0 0 0-1-1h-2L9 2H5L3.5 4h-2a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1V5z"
/>
<path
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
d="M7 9.75a2.25 2.25 0 1 0 0-4.5 2.25 2.25 0 0 0 0 4.5z"
/>
<symbol id="camera2" viewBox="0 0 13 12">
<g clipPath="url(#a)">
<path
fillRule="evenodd"
d="M4.443 1.457a.429.429 0 0 1 .343-.171h3.428c.135 0 .262.063.343.171L9.714 3h1.5A1.286 1.286 0 0 1 12.5 4.286v5.143a1.286 1.286 0 0 1-1.286 1.285H1.786A1.285 1.285 0 0 1 .5 9.43V4.286A1.286 1.286 0 0 1 1.786 3h1.5l1.157-1.543zM8.61 6.61a2.11 2.11 0 1 1-4.22 0 2.11 2.11 0 0 1 4.22 0z"
clipRule="evenodd"
/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h12v12H0z" transform="translate(.5)" />
</clipPath>
</defs>
</symbol>
<symbol id="favorite2" viewBox="0 0 14 14">
<path
Expand Down
8 changes: 7 additions & 1 deletion src/components/Common/TopBar/TopBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ const BackLink = ({ state }: TopBarProps) => {

return (
<Link to="#" onClick={handleBack}>
<SvgIcon variant="arrowLeft" stroke={vars.colors.gray5} width={20} height={20} />
<SvgIcon
variant="arrowLeft"
stroke={vars.colors.gray5}
width={20}
height={20}
style={{ transform: 'translateY(2px)' }}
/>
</Link>
);
};
Expand Down
1 change: 0 additions & 1 deletion src/components/Common/TopBar/topBar.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export const container = style({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: '0 20px',
backgroundColor: vars.colors.white,
transform: 'translateX(-50%)',
zIndex: 1001,
Expand Down
1 change: 1 addition & 0 deletions src/components/Common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ export { default as WriteButton } from './WriteButton/WriteButton';
export { default as Text } from './Text/Text';
export { default as Indicator } from './Indicator/Indicator';
export { default as TopBar } from './TopBar/TopBar';
export { default as StarRating } from './StarRating/StarRating';
export { default as ShowAllButton } from './ShowAllButton/ShowAllButton';
22 changes: 6 additions & 16 deletions src/components/Members/MemberImage/MemberImage.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,32 @@
import { useState } from 'react';
import type { CSSProp } from 'styled-components';
import styled from 'styled-components';

import { container } from './memberImage.css';

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 MemberImage = ({ src, width = 48, height = 48 }: MemberImageProps) => {
const [isError, setIsError] = useState(false);

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

return (
<StyledMemberImage
<img
className={container}
src={isError ? DefaultMemberImage : src}
alt={alt}
alt="사용자 프로필"
width={width}
height={height}
css={css}
onError={handleImageError}
/>
);
};

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};
`;
6 changes: 6 additions & 0 deletions src/components/Members/MemberImage/memberImage.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { style } from '@vanilla-extract/css';

export const container = style({
borderRadius: '50%',
objectFit: 'cover',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Meta, StoryObj } from '@storybook/react';

import MemberModifyInput from './MemberModifyInput';

const meta: Meta<typeof MemberModifyInput> = {
title: 'members/ MemberModifyInput',
component: MemberModifyInput,
args: {
nickname: '펀잇',
},
};

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

export const Default: Story = {};
50 changes: 21 additions & 29 deletions src/components/Members/MemberModifyInput/MemberModifyInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Heading, Spacing, Text, Input, useTheme } from '@fun-eat/design-system';
import type { ChangeEventHandler } from 'react';
import styled from 'styled-components';

import { container, inputWrapper, letterCount } from './memberModifyInput.css';

import { Text } from '@/components/Common';

const MIN_LENGTH = 1;
const MAX_LENGTH = 10;
Expand All @@ -11,36 +13,26 @@ interface MemberModifyInputProps {
}

const MemberModifyInput = ({ nickname, modifyNickname }: MemberModifyInputProps) => {
const theme = useTheme();

return (
<MemberModifyInputContainer>
<Heading as="h2" size="xl" tabIndex={0}>
<>
<Text size="caption2" weight="semiBold">
닉네임
</Heading>
<NicknameStatusText color={theme.textColors.info} tabIndex={0}>
{nickname.length}자 / {MAX_LENGTH}
</NicknameStatusText>
<Spacing size={12} />
<Input
value={nickname}
customWidth="100%"
onChange={modifyNickname}
minLength={MIN_LENGTH}
maxLength={MAX_LENGTH}
/>
</MemberModifyInputContainer>
</Text>
<div style={{ height: 8 }} />
<div className={container}>
<Text className={letterCount} as="span" size="caption4" weight="medium" color="disabled">
{nickname.length} / {MAX_LENGTH}
</Text>
<input
className={inputWrapper}
value={nickname}
onChange={modifyNickname}
minLength={MIN_LENGTH}
maxLength={MAX_LENGTH}
/>
</div>
</>
);
};

export default MemberModifyInput;

const MemberModifyInputContainer = styled.div`
position: relative;
`;

const NicknameStatusText = styled(Text)`
position: absolute;
top: 0;
right: 0;
`;
34 changes: 34 additions & 0 deletions src/components/Members/MemberModifyInput/memberModifyInput.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { vars } from '@/styles/theme.css';
import { style } from '@vanilla-extract/css';

export const container = style({
position: 'relative',
width: '100%',
border: `1px solid ${vars.colors.border.default}`,
borderRadius: 6,
boxSizing: 'border-box',

selectors: {
'&:focus-within': {
outline: `1px solid ${vars.colors.primary}`,
border: `1px solid transparent`,
},
},
});

export const inputWrapper = style({
width: '90%',
height: 44,
paddingLeft: 16,
outline: 'none',
});

export const letterCount = style({
position: 'absolute',
width: '10%',
top: 14.5,
right: 16,
display: 'flex',
alignItems: 'center',
background: vars.colors.white,
});
Loading

0 comments on commit 0e8de8d

Please sign in to comment.